I have a problem with Java Swing, in particular with JLayeredPane.
I have a Deck manager which contains 4 JPanels in a JLayeredPane, but when i add an object to a Pane, then switch to another, the objects turns invisible at first, but when i pass with the mouse on, it returns visible even thoug i'm on a different Panel, here's the code:
deckSelector = new JLayeredPane();
Point origin = new Point(30, 0);
for (int i = 0; i < types.length; i++) {
Deck deck = new Deck(types[i], colors[i], origin);
deckSelector.add(deck, i);
decks[i] = deck;
}
to change
int j = 0;
boolean found = false;
for(int i=0; i<types.length; i++){
if(selectors[i].isSelected()){
deckSelector.setLayer(decks[i], 3);
found = true;
j=2;
} else
if(!selectors[i].isSelected()){
deckSelector.setLayer(decks[i], j);
if(found) j--;
else j++;
};
}
to add a card:
Card btnNewButton = new Card("Name Card");
add(btnNewButton);
I have a deck manager which is the main JLayerdPane, it has 4 decks overlayed, in which i can add cards, but when i switch from a deck to another, the card is still visible. Can anyone help me?
but when i pass with the mouse on
A mouseOver event is generate for the component. In the case of a JButton the border is changed, so the component needs to repaint itself. So that is why the component becomes visible.
The point of using a JLayeredPane is to see all the layers at the same time. Its just that some components will be stacked on top of others.
If you only want to see a single panel at a time, then you should be using a Card Layout. Then you can swap which panel is visible and any given time.
If you think you really need to use a JLayeredPane then try using setVisible(false) on the panel you don't want to see. This should prevent events from being passed to components on the panel in that layer.
Related
I am builing an expanding Window/layout that shall expand/shrink on supplied data, possibly expanding to fill the browser window.
Edit: The scroll bars shall be on the work-area, not the window.
So far i have only managed to get it working vertically with a simple list of labels (see simple_list.png).
Vertical scrollbar appear when browser window filled vertically Horizontal scrollbar always present and width of window/layout seems directed by length of panel title and window icons at top-right.
Edit: Scroll bars OK on Panel. No horizontal expansion.
It fails completeley for a GridLayout (see gridlayout.png).
Edit: I.E no scrollbars on work-area (Panel)
The final layout is supposed to have a central work area and header, footer, left/right areas. The work area to expand according to data.
Barked up the wrong tree? CSSLayout? Not for Vaadin?
Any help/guidance appreciated.
A simplified test case below (Vaadin 7, subclassing Window).
public TestWindow() {
super.setSizeUndefined();
VerticalLayout vL = new VerticalLayout();
vL.setSizeFull();
super.setContent(vL);
//vL.addComponent(buildHeader());
Panel workArea = new Panel();
workArea.setSizeFull();
workArea.setCaption("View");
vL.addComponent(workArea);
vL.setExpandRatio(workArea, 1f);
//vL.addComponent(buildFooter());
//-----------------------------
VerticalLayout view = new VerticalLayout();
view.setSizeUndefined();
workArea.setContent(view);
for (int i=0; i < 100; i++) {
String s = "view line "+i;
for (int j=0; j < 10; j++) {
s += "____________________"+j;
}
Label line = new Label(s);
line.setSizeUndefined();
view.addComponent(line);
}
//=============================
/*
VerticalLayout view = new VerticalLayout();
view.setSizeUndefined();
workArea.setContent(view);
GridLayout gl = new GridLayout();
gl.setSizeUndefined();
view.addComponent(gl);
view.setExpandRatio(gl, 1);
gl.setColumns(2);
for (int i=0; i < 100; i++) {
Label line = new Label("view line "+i);
line.setSizeUndefined();
gl.addComponent(line);
}
*/
//------------------------------
center();
setModal(true);
setDraggable(true);
UI.getCurrent().addWindow(this);
}
simple_list.png
gridlayout.png
Vaadin documentation says:
If a sub-window has a fixed or percentual size and its content becomes too big to fit in the content area, a scroll bar will appear for the particular direction. On the other hand, if the sub-window has undefined size in the direction, it will fit the size of the content and never get a scroll bar.
Source: https://vaadin.com/docs/v7/framework/layout/layout-sub-window.html
I'm trying to build an array of JButton images. These will have a toggle (viewable/not viewable) thus why I chose to use JButtons.
These buttons also have a background image. When I place one button to the pane, this is in Java obviously, it works. But when I load the buttons in to an array and try to print them to the pane, nothing....I would appreciate the help. Here's what I have.
JButton card = new JButton();
JButton[] deck = new JButton[9];
int xLoc=20, yLoc=5;
card.setIcon(new ImageIcon("Back.jpg"));
card.setSize(200,250);
card.setVisible(true);
for(int i=0; i<9;i++)
{
deck[i]=card;
}
for(int i=1;i<10;i++)
{
deck[i-1].setLocation(xLoc,yLoc);
pane.add(deck[i - 1]);
validate();
xLoc+=220;
if(i%3==0)
{
yLoc+=265;
}
In my mind, I am creating a card object with a size and a background and visible, and then loading the same card over and over in to my array, then adding it to the pane, that has a background. It's not causing any errors or exceptions, but it's not placing anything but the background to the pane.
Thanks in advance. I will be honest and say this is a homework assignment, but I am exceeding the expectations by going this route. I know I can create individual buttons and put them on the screen. I know how, and can do it. What I want to do is not covered in the scope of the class.
This is a project, not just an assignment, and the instructor encouraged learning new things on our own and expanding the project. So, by helping me you are not helping me cheat, but helping me learn something more than the class teaches. Thanks!
Your basic problem comes down to the fact that a component can only reside within a single parent...
// You create a card...
JButton card = new JButton();
// You create an array of buttons
JButton[] deck = new JButton[9];
int xLoc=20, yLoc=5;
// You set the icon
card.setIcon(new ImageIcon("Back.jpg"));
// This is not a good idea...
card.setSize(200,250);
// JButton is visible by default...
card.setVisible(true);
// Start your loop...
for(int i=0; i<9;i++)
{
// Assign the card reference to an element in the array...
deck[i]=card;
// Add the card, via the array to the component...here's your problem...
pane.add(deck[i - 1]);
In adding card to pane, it is first removed from pane, as it can only have one parent. What you need to do, is assign a unique instance of JButton to each element in the array
// You create an array of buttons
JButton[] deck = new JButton[9];
// Start your loop...
for(int i=0; i<9;i++)
{
// Assign the card reference to an element in the array...
deck[i]=new JButton();
// You set the icon
deck[i].setIcon(new ImageIcon("Back.jpg"));
// This is not a good idea...
deck[i].setSize(200,250);
// JButton is visible by default...
deck[i].setVisible(true);
// Add the card, via the array to the component...here's your problem...
pane.add(deck[i]);
Now, I can't see from your code snippet, but it would appear you are trying to use a null layout, this is highly inadvisable. Instead, make the time to learn and understand how to use appropriate layout managers.
If you're not using a null layout or don't know what I'm talking about, then things like setSize and setLocation won't work the way you expect them to...
I'm currently programming a Calendar in Java. The Calendar itself fills out perfectly fine with the Month and Year being displayed in JComboBoxes above the grid below it. The Grid itself is full of empty JLabels or JButtons (for the days of the month). The JComboBoxes are linked to ActionListeners, which detect the user changing information (confirmed by System.out.print statements). However, I cannot find a way to "redraw" the JPanel after this occurs. The method being called completely creates a new JPanel and adds in the new JLabels/JButtons, but nothing on the JFrame is updated after this happens. I have attempted using both the repaint and revalidate on the whole JPanel (which includes the JComboBoxes and the grid below it in a BorderLayout), the JPanel with only the grid, and the JFrame, but nothing happens. Does anyone have any ideas what is wrong?
// This code is within the build() method that builds the GUI.
// This method adds the centerPanel into the mainPanel
yearChoice.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
int i = yearChoice.getSelectedIndex();
if (i >= 0) {
yy = Integer.parseInt(yearChoice.getSelectedItem()
.toString());
//System.out.println("Year=" + yy);
compute();
}
}
});
private void compute(){
elements = new int[6][7];
// OMITTED is the code that determines whether a cell in the array should be an empty
// JLabel or a JButton. This code is based on the Calendar, and does work properly,
// but I can't figure out how to get the new Month/Year to show up on a new Panel
centerPanel = new JPanel(new GridLayout(7, 7));
JLabel sunday = new JLabel("S"),
monday = new JLabel("M"),
tuesday = new JLabel("T"),
wednesday = new JLabel("W"),
thursday = new JLabel("Th"),
friday = new JLabel("F"),
saturday = new JLabel("S");
centerPanel.add(sunday);
centerPanel.add(monday);
centerPanel.add(tuesday);
centerPanel.add(wednesday);
centerPanel.add(thursday);
centerPanel.add(friday);
centerPanel.add(saturday);
for(int i = 0; i < 6; i++){
for(int j = 0; j < 7; j++){
if(elements[i][j] == -1){
centerPanel.add(new JLabel(" "));
}else{
centerPanel.add(new JButton("" + elements[i][j]));
}
}
}
// Here is where I attempt to repaint the centerPanel for the JPanel, but it
// doesn't work
}
The method being called completely creates a new JPanel and adds in the
new JLabels/JButtons, but nothing on the JFrame is updated after this
happens. I have attempted using both the repaint and revalidate on the
whole JPanel (which includes the JComboBoxes and the grid below it in
a BorderLayout), the JPanel with only the grid, and the JFrame, but
nothing happens. Does anyone have any ideas what is wrong?
you call another JPanel for (re)validate & repaint
updates are out of visible rectangle on the screen, put JPanel to the JScrollPane
if updates are out of visible rectangle you can to call JFrame.pack(), but in this case JFrame will be changed its Dimension on the screen
The method being called completely creates a new JPanel and adds in
the new JLabels/JButtons, but nothing on the JFrame is updated after
this happens.
for why reason you re_create a JPanel, create that once time and to play with setVisible(false/true)
don't re_create a JPanel, put these (two or three JPanels) to the CardLayout, then any changes will be only switch betweens views
for better help sooner post an SSCCE, short, runnable, compilable
code example
I wanna fix a 2D board for a game. I've already fixed other panels for the Gui and everything goes well. But the panel for the board cant be printed on the window. I'm a bit confused about it as i think i've followed the same ideas as for the others panels i need.
Here's what i've done:
EDIT:
what I'm trying to do is fix a board panel for the game according to the dimensions of the it,hold every square in an array in order to use it after wherever it;s needed. I draw each little square of it with the method draw and put it back to the panel. So, each square on the board is a panel. This is the idea. But as u can see. There are troubles/errors on it.
EDIT: code updated.
just found a part of the problem. i thought first that i had set background to squared, but i didnt. with this one it appears on the panel a wide black "column". Unfortunately,still none squares. :(
One More EDIT:
Also,i realized that draw method is never called. when i put the draw method in the following method i can see the squares but they remain small. I redefine them with setSize but still no change.
How can I use paint method to edit the panels properly???? As it is now it can't. Even it can't return an object(eg panel) as it's polymorphic void!
/**
*Method used to construct the square in the area of the
*gui's grid. In this stage a GUISquare array is being constructed,
* used in the whole game as
*a mean of changing a square graphical state.
*#param squares is the squares array from whom the gui grid will be
*constructed.
*#see getSquare about the correspondance beetween a squareModel and
* a GUISquare.
*/
private void initBoardPanel(SquareModel[][] squares){
BoardPanel.setLayout(new GridLayout(height ,width )); //set layout
SquareRenderer[][] Squares;
JPanel[][] grid;
Squares=new GUISquare[height][width()];
grid=new JPanel[height()][width()];
for (int i=0; i<height(); i++){
for (int j=0; j<width() ; j++){
SquareRenderer kou=new SquareRenderer(i,j);
kou.setSquare(myGame.getSquares()[i][j]);
//NOTE: THE FOLLOWING DRAW METHOD CANT BE CALLED!!!?
if (myGame.getSquares()[i][j] instanceof SimpleSq ){
kou .paintPanel(i,j,"");}
else if (myGame.getSquares()[i][j] instanceof ActionSq )
{ kou .paintPanel(i,j);
}
//JUST BECAUSE DRAW CANT BE CALLED I PUT ITS CODE HERE:
//JUST TO CHECK:
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JLabel label1 = new JLabel("Move To "+myGame.getSquares()[i][j].getGoTo());
JLabel label2 = new JLabel(""+myGame.getSquares()[i][j].getSquare());
panel.setBackground(Color.ORANGE);
panel.add(label2, BorderLayout.NORTH);
panel.add(label1, BorderLayout.CENTER);
panel.setSize(250,250);
///////// <--until here ---paint method<---
kou.add(panel);
kou.setVisible(true);
kou.setBackground(Color.BLACK);
Squares[i][j]= kou;
BoardPanel.add(kou);
BoardPanel.setVisible(true);
BoardPanel.setBackground(Color.WHITE);
}
}
this.add(BoardPanel,BorderLayout.WEST);
// this.pack(); //sets appropriate size for frame
this.setVisible(true); //makes frame visible
}
IMPLEMENTED BY SQUARERENDERER:
/**
* Transformer for Snake/Ladder
* <br>This method is used to display a square on the screen.
*/
public void paintPanel(int i,int j) {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JLabel label1 = new JLabel("Move To"+myGame.getSquares()[i][j].getGoTo());
JLabel label2 = new JLabel(""+myGame.getSquares()[i][j].getSquare());
JSeparator CellSeparator = new JSeparator(orientation);
panel.add(CellSeparator);
panel.setForeground(Color.ORANGE);
panel.add(label2, BorderLayout.NORTH);
panel.add(label1, BorderLayout.CENTER);
}
I see a couple things that are problematic:
When using a layout manager, you should avoid calling setSize. Most layout managers will simply override it. You should use setPreferredSize, setMinimumSize, and setMaximumSize instead, which provide hints to the layout manager.
It doesn't look like the draw method of SquareRenderer ever adds the panel you create to anything. You should either add panel to the SquareRenderer in the last line of draw or (better) add the sub-components directly to the SquareRenderer instead.
I'm having a little trouble building the grids for a Battleship game for my Java class. So far, I can easily make a for loop to add JPanel or JButton objects to the JFrame. However, my issue is that I'll need to use those Panels or Buttons again when playing the game (such as clicking on a button to see if your opponent put a ship on that square, et cetera). Is there a simple way in Java to initialize reference variables for a LOT of objects? Or will I have to declare all of them individually?
You could try a multi dimensional array of JPanels (or any other object). Create an array with the same size as your grid. The line below initializes an array with 5 rows and 5 columns.
JPanel[][] battleField = new JPanel[5][5];
Use nested for loops to create the panels in the array.
for (int rowIndex = 0; rowIndex < battleField.length; rowIndex++)
{
for (int cellIndex = 0; cellIndex < battleField[rowIndex]; cellIndex++)
{
battleField[rowIndex][cellIndex] = new JPanel();
}
}
If you want to reference the battleField array later on you would just make it into a instance variable.
For a battleship game, you most likely want to retrieve the location of a button after is has been clicked. You can create a hashtable using your buttons as keys and the point it is located at as a value.
HashMap<JButton, Point> buttonMap = new HashMap<JButton, Point>();
for (int x = 0; x < COLUMNS; x++)
{
for (int y = 0; y < ROWS; y++)
{
JButton btn = new JButton();
btn.addActionListener(this);
buttonMap.put(btn, new Point(x, y));
//then add the button to your container
}
}
The in your actionPerformed method you can convert the button to the point it is located at like this.
JButton btn = (JButton)actionEvent.getSource();
Point p = buttonMake.get(btn);
Of course you will need to properly handle error conditions such as source not being a button or the button not being in the map...
You can always extend JButton to keep track of the info you need. A simple example:
class MyButton extends JButton{
private MyGameInfo mygameInfo;
private int buttonId;
//More fields....
//Getters/Setters
}
Then instead of creating and adding JButton objects to your layout, create MyButton objects(which is also a JButton so your layout will not be effected) and use its extra functionality for your game logic.
For reference, here is a related matching game that uses a grid of buttons. This related answer demonstrates the application of the Model–View–Controller pattern to a simple game.