I have a JPanel with a GridLayout(1,0) set to a JFrame Borderlayout.SOUTH, there are placed a couple of buttons in here (when pressed they change a variables value to the index of the created button).
Everything is added correctly, but when I try to update the JPanel it does work at first (only when window is maximized). But then when I go over a button (or all the buttons) it goes back to what the original content of the panel.
I've tried invalidate, validate, repaint, jframe.setvisible(true) - none of these seem to work properly.
Any ideas?
private void toonHand(){
JPanel pnlSouth = new JPanel(new GridLayout(1,0));
JButton[] btnArr =new JButton[50];
ArrayList<Kaart> Thand=uno.getSpeler(0).getHand();
for(int i=0;i<Thand.size();i++){
final int T=i;
btnArr[i]=new JButton();
btnArr[i].setIcon(Thand.get(i).getImg());
btnArr[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
iKaart=T;
}
});
pnlSouth.add(btnArr[i]);
}
Hoofdvenster.remove(pnlSouth);
Hoofdvenster.add(pnlSouth, BorderLayout.SOUTH);
}
The problem was that i was just removing the panel, changing the content and adding it again.
Apparently this was giving some issues with displaying the content.
I fixed it by putting the panels as global variables, and splitting up the making and updating of the panels. So in every update i remove the panel, make the panel a new Panel and then i make it again.
Related
i recently code a system homepage that include the background image. After i set the background, the button that i created cannot show properly. It just appear after i use the mouse and point to the buttons' location. Can someone teach me how to fix this problem? Your help are appreciated. The codes are as below:
public class HomePage extends JFrame{
private JPanel button = new JPanel();
private JButton time = new JButton("Bus Schedule");
private JButton reserve = new JButton("Booking");
private JButton info = new JButton("About Us");
Container con = getContentPane();
public HomePage(){
setTitle("Bus Reservation System");
setSize(650,500);
setLocation(360,100);
setVisible(true);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBackground();
setButton();
}
public void setBackground(){
JLabel background = new JLabel(new ImageIcon("C:/User/Desktop/Assignment/bg.jpg"));
con.add(background);
background.setLayout(new FlowLayout());
con.add(button);
}
public void setButton(){
Font but = new Font("Serif" , Font.ITALIC , 20);
info.setFont(but);
time.setFont(but);
reserve.setFont(but);
button.add(info);
button.add(time);
button.add(reserve);
con.add(button);
}
After you call setVisible(true), if you perform certain actions, you must manually validate() or revalidate() your window.
It is simpler to just call setVisible() after you have initialized all of the desired settings and membership of the window.
/* setVisible(true); -- wrong place */
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBackground();
setButton();
setVisible(true); // proper place
Simple mistake (probably a typo?), you are setting the layout of the JLabel, you intended to set the layout of the Container. Do con.setLayout(new FlowLayout()); instead of background.setLayout(...)
Also, I believe your path to the file is incorrect. For testing, just put the file in the project and do a path like "bg.jpg", if that works, we can verify this. For me that works. The reason I believe this is the issue is because you specify C:/Users, but then never give the folder for the specific User. A correct path would be C:/Users/Your_name/Desktop/Assignment/bg.jpg
I don't know for sure on that path part, since I'm not on your system. However, for me, if I run your code in my eclipse, this fixes it.
edit:
One last thing, the image isn't really going to be a "background" image with the current code because it will move the buttons underneath it instead of on top of it with the FlowLayout. You may want to use a different Layout.
First of all as already noted, all components should be added to the frame BEFORE invoking setVisible(true) on the JFrame.
JLabel background = new JLabel(new ImageIcon("C:/User/Desktop/Assignment/bg.jpg"));
con.add(background);
background.setLayout(new FlowLayout());
con.add(button);
Based on the above code you are adding two components to the content pane so the hierarchy of your GUI looks like this:
- frame
- content pane
- background
- button
It seems to me you want your GUI to look like this:
- frame
- content pane
- background
- button
So your code should be:
JLabel background = new JLabel(new ImageIcon("C:/User/Desktop/Assignment/bg.jpg"));
con.add(background);
background.setLayout(new FlowLayout());
//con.add(button);
background.add( button );
I'm doing a little program for me, with NetBeans. I need no create many JButtons on a JPanel but i can't do it. The JPanel has been generated by the NetBeans editor on a JFrame (also made it by the NetBeans editor)
This is the code:
public static ArrayList<Account> accounts = Account.accounts;
public verCuenta() {
initComponents();
panel.setVisible(true);
Account ac;
JButton button;
int size= accounts.size();
for(int i=0;i<size;i++){
button = new JButton(accounts.get(i).getName());
button.setVisible(true);
button.addActionListener(null);
button.setPreferredSize(new Dimension(50,30));
panel.add(button);
}
I managed to get a single Button to pop up,
maybe start with this first, then try to get several, then get your loop working
// Create a new button:
JButton b1 = new JButton("ok");
// Set the location and size of the button:
b1.setSize(100, 26);
// Add the button to the window:
jPanel1.add(b1);
//Repaint the Panel to make visible
jPanel1.repaint();
It only works when you set a size, just checked in Netbeans.
You can also specify the location, using
b1.setLocation(100, 100);
btw, whole frame is in gridbag layout
you need to add all elements to the panel and then call the setVisible method.
Additions after calling the setVisible method are not per se taking into account.
I'm working on large scale program. As you can see I have one main JFrame and about 20 menu items on that. Each menu item must pop up a new window. At the beginning I have created a JLayeredPanel and then I assigned each menu item to one JPanel which is inside JFrame.Then I put 25 panel in JLayeredPanel... Default all the panels are set to invisible like:
panel1.setVisible(false);
panel2.setVisible(false);
so on
When user click on one menu item, its JPanel will be visible and rest are invisible. It looks messy and I have 5000 lines code. I used InternalFrame and TabbedPane but I'm not happy with them. I want to split my code in different JPanel classes and assign them to the main JFrame. I mean when user clicked on each menu item it will call the external JPanel and render it on the JPanel on the main JFrame. I am using design mode in netbeans and it does everything for me but the simpled structure is like this and it is not working:
public class NewJPanel extends JPanel{
//I have added buttons and etc on this panel
......
}
public class frame extends JFrame(){
JPanel panel = new JPanel();
.....
Public frame(){
frame.add(panel);
}
......
//When use click on the any button on the panel
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
//this is not working
NewJPanel fi = new NewJPanel ();
panel1.add(fi);
//or I tested this way separately but it did not work
panel1.remove();
panel1 = new NewJPanel();
add(panel);
invalidate();
}
}
please give me any suggestion how I can control this program in splited classes in professional way.
remove JPanel from JFrame.getContentPane.remove(myPanel)
add a new JPanel with constants, everyhing depends of used LayoutManager and its methods implemented in API
call JFrame.(re)validate() and JFrame.repaint() as last code lines, if everything is done, these notifiers correctly repaint available area
again to use CardLayout, there isn't signoficant performance or memory issue
Please give me any suggestion how I can control this program in splited classes in proressional way.
Ok.
You should put all of your JPanels in a JTabbedPane. The JTabbedPane would be added to the JFrame.
The JFrame, JTabbedPane, and each JPanel would be constructed in a separate class.
You use Swing components, rather than extending them. The only reason you extend a Swing component is if you override one of the component methods.
You should also create model classes for each of the JPanels, as well as a model class for the application.
Read this article to see how to put a Swing GUI together.
make's code better
public class NewJPanel extends JPanel{
//I have added buttons and etc on this panel
......
}
public class frame extends JFrame(){
JPanel panel = new JPanel();
.....
Public frame(){
//frame.add(panel); you dont need call frame because extends JFrame in frame class
add(panel);
......
//When use click on the any button on the panel
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
//this is not working
NewJPanel fi = new NewJPanel();
add(fi);
//or I tested this way separately but it did not work
/*panel1.remove();
panel1 = new NewJPanel();
add(panel);
invalidate();you must define panel1 before use it,like :JPanel panel1 = new JPanel();*/
}
}
Currently I have a JFrame 'window' with the layout set to BorderLayout. I have a panel for the west and center sections, with two alternating panels for south. In the west section I have 5 labels. In the center section I have 5 JTextField components. And in the south section i want to alternate between two panels (both FlowLayout) &(each one holds 2 separate buttons).
Right now I initialize and the south section has the correct two buttons, but when i call my event action listener only half of the method is called correctly. Behind the scenes i have the menu item connected to the listener, and it seems to work correctly. the clear text method works but changing the south panel does not
here are the panels and frame being initialized(they are initialized in the class constructor):
myWindow = new JFrame();
myWindow.setLayout(new BorderLayout());
myWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
sPanel1.add(prevButton);
sPanel1.add(nextButton);
sPanel2.add(okButton);
sPanel2.add(cancelButton);
myWindow.add(sPanel1, BorderLayout.SOUTH);
myWindow.add(wPanel, BorderLayout.WEST);
myWindow.add(cPanel, BorderLayout.CENTER);
//so here, at this line, i have tried the adding sPanel2 at the south position,
//after i have added sPanel1. The result is that sPanel2 overrides sPanel1 (like i
//assumed it would). However, the same doesnt work in the editAddEvent method
//below. both lines are called but only the cleartextfields method works.
//why is this?
public class myEvent implements ActionListener{
#Override
public void actionPerformed(ActionEvent arg0) {
myWindow.add(sPanel2, BorderLayout.SOUTH);
clearTextFields();
myWindow.revalidate();
myWindow.repaint();
Container content = myWindow.getContentPane();
content.revalidate();
content.repaint();
}
}
public void clearTextFields(){
fNameTxt.setText("");
mNameTxt.setText("");
lNameTxt.setText("");
}
the clear textfields method works perfectly, it clears my JTextFields
I am having trouble moving this JLabel across this JPanel? I put the code below. Basically what is supposed to happen, is the JLabel called "guy" slowly moves to the right. The only problem is, that the JLabel isn't refreshing it just disappears after the first time I move it.
public class Window extends JFrame{
JPanel panel = new JPanel();
JLabel guy = new JLabel(new ImageIcon("guy.gif"));
int counterVariable = 1;
//Just the constructor that is called once to set up a frame.
Window(){
super("ThisIsAWindow");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(panel);
panel.setLayout(null);
}
//This method is called once and has a while loop to exectue what is inside.
//This is also where "counterVariable" starts at zero, then gradually
//goes up. The variable that goes up is suposed to move the JLabel "guy"...
public void drawWorld(){
while(true){
guy.setBounds(counterVariable,0,50,50);
panel.add(guy);
counterVarialbe++;
setVisible(true);
try{Thread.sleep(100)}catch(Exception e){}
}
}
Any thoughts as to why the JLabel is just disappearing instead of moving to the right after I change the variable "counterVariable".
-Thanks! :)
Your code is causing a long-running process to run on the Swing event thread which is preventing this thread from doing its necessary actions: paint the GUI and respond to user input. This will effectively put your entire GUI to sleep.
Issue & suggestions:
Never call Thread.sleep(...) on the Swing Event Dispatch Thread or EDT.
Never have a while (true) on the EDT.
Instead use a Swing Timer for all of this.
No need to keep adding the JLabel to the JPanel. Once added to the JPanel, it remains there.
Likewise, no need to keep calling setVisible(true) on the JLabel. Once visible, it remains visible.
Call repaint() on the container holding the moving JLabel after you've moved it to request that the container and its children be re-drawn.
e.g.,
public void drawWorld(){
guy.setBounds(counterVariable,0,50,50);
int timerDelay = 100;
new javax.swing.Timer(timerDelay, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
countVariable++;
guy.setBounds(counterVariable,0,50,50);
panel.repaint();
}
}).start;
}
caveat: code not compiled, run, or tested in any way