How do I re-initialize a panel with a GridLayout? - java

I'm writing a small Calendar application which lets my manage important dates and events of my study. I'm working with java.awt.
A single month is drawn onto a panel with a 7*7 BorderLayout. When the program is started, the panel is drawn with the following method:
public void drawCalendarP(String dateS){
if(mf != null && calendarP != null){
mf.remove(calendarP);
calendarP.removeAll();
}
calendarP = new Panel();
calendarP.setLayout(new GridLayout(7,7,10,10));
//...
day[0] = new Button("1");
day[0].addActionListener(...);
day[0].setVisible(true);
calendarP.add(day[0]);
/*each day of the month is represented by a button. I've put the
initialization of the 'Day-buttons' in its own method which is called
frome here, but this is basically what it does.*/
//...
mainframe.add(calendarP);
}
}
Now, when I start the program and this method is firstly called, everything works just as intended. However, I included a button which lets you switch between individual months, and this is where the problem arises.
Because in order to draw a new month, I have decided to just call the method drawCalenderP() again, but with a different String dateS. And again, if you put this String in manually before the start of the program, it will happily draw you any month you want.
However, if I call the method again with said button, it will do the following:
It will re-draw the panel, along with its background and everything (as intended)
It will re-initialize all the components for that panel (as intended)
But it wont draw the new components back onto the panel (not as intended)
I have no idea why that happens. It should add the new components, just the way it does when you call the method the first time, but the components just won't show up on the panel.
The thing is; if I draw the button without the help of the GridLayout, let's say with setSize(w,x) and setLocation(y,z), everything will work just fine again. So the problem lies somewhere within the GridLayout, but I just can't figure it out.
Is there a way to do this without scrapping the entire layout-thing and doing the positioning of the components manually?

Related

Panel.repaint() doesn't seem to be refreshing panel

I'm having some issues repainting a JPanel on my GUI with default values.
The code I'm using right now is below, again, I'm not used to, nor really knowledgeable about java code, so forgive me for making rookie mistakes:
private void btnResetActionPerformed(java.awt.event.ActionEvent evt) {
...
pnlWagens1 = new pnlWagens();
UpdateGUI();
}
private void UpdateGUI(){
pnlWagens1.repaint();
}
So far I've tried the above code, as well as setting the JPanel to null, repainting, inserting a new instance of the panel, repainting again.
Nothing so far has been fruitful, as in the end, I'm still stuck with the old panel (and it's values) being shown on my GUI.
Basically, I make a panel with a green background initially, make the background red, then resetting the panel to have a green background again. However in the end, after hitting Reset, it still shows the old panel with the red background.
Any insight as to what I may be doing wrong/overlooking would be greatly appreciated.
Assuming this is all the relevant code (and that UpdateGUI doesn't use add or remove with the panel reference you have there), then changing what object pnlWagens1 refers to in your local class won't change other references that still refer to the old object. The old object pnlWagens1 is still referenced by Swing in another location, from when you originally called add on some container.
What you need to do is to remove pnlWagens1 from the container, change pnlWagens1 like you are doing now, readd pnlWagens1 to the container, and call then call both revalidate() and repaint() on the container.

Update JFrame window

I'm doing a simple java application that essentially shows a certain amount of letters (ABCDE etc) from an array, each one displayer in a portion of a grid. There are two buttons, one that will shift the letters to the left (so that one shift will become BCDEA and the right shift will go EABCD).
I've got the shifting and everything else working, as I've tested using a System output. But how do I get the window to refresh and show me the updated JLabels? They stay the same (ABCDE) after I shift them.
I've tried revalidate() and repaint() both inside the buttons' ActionListeners and on the shift method that they call, but nothing happens. Any tips on this?
I've tried revalidate() and repaint()
You only use those methods when you create a new component and add the component to a visible GUI. So it sounds like you are trying to remove/add the labels in the new order you want the labels to be displayed.
Maybe an easier approach is to leave the label in the same order but just change the text on each label. Then all you need to do is
label.setText();
and the label will repaint itself automatically without you invoking revalidate() and repaint().

Adding components in GUI upon repaint method

I'm not understanding Java GUI's as well as I thought. In my paint method for a frame, I'd like to wipe all of the current buttons, and add new ones. (The overall goal is to have an interface where the user can see characters and click on the buttons to download documents related to the character. Since every character is different, when the user selects a new user from my list, a new set of documents and buttons will be available to them.)
This is a test frame that I just wrote that shows where things go sideways. It has the similar paradigms that I use in my actual program, without too much clutter:
public class GUITest extends JFrame
{
/**
* #param args
*/
public static void main(String[] args)
{
Container gui_test = new GUITest();
}
private JComponent content = null;
public GUITest()
{
super();
setVisible(true);
}
public void paint(Graphics g)
{
this.removeAll();
content = new JPanel();
JComponent test_button = new JButton("New Button 1");
JComponent button = new JButton("New Button 2");
content.add(button);
content.add(test_button);
this.add(content);
super.paint(g);
}
}
Without the call to removeAll(), buttons will continue to be thrown on top of the JPanel, but with the call, nothing shows up. I don't know why this is, as I'm adding the components appropriately, right?
Edit
Got it, let me give you a more detailed breakdown. A client is navigating my program by looking at a list of characters in a game on a west panel. They can select a row from the list which will show char details on the east panel. The details are an image and description. Recently, I added relevant documents for that particular char, which will show on the bottom of the east panel. I created key listener's, so the client can quickly view the document by pressing a num key, but I also want to give them the ability to click on the button to launch a pdf view and see the contents of the document.
Since every char has different related docs and different number of docs, I repainted the buttons every time, to reflect the amount of related docs and the appropriate titles for the docs. This is where the repaint is acting strange. You gave me a good explanation of what's going wrong, but I don't know how to give the client access to the docs now, aside from painting a description of the doc along with the hot key needed to launch it. Does that make sense?
Never add components to your GUI or remove components in the paint or paintComponent methods. Just don't do it. Ever. Period.
These methods are for drawing only, and need to be as fast as possible, else your program will appear unresponsive. Not only that, you do not have full control over when or even if these methods will be called, so program logic and structure should not go into these methods.
Instead react to user events with event listeners such as ActionListeners, ListSelectionListeners, or with key bindings.
Edit
Regarding
Got it, let me give you a more detailed breakdown. A client is navigating my program by looking at a list of characters in a game on a west panel. They can select a row from the list which will show char details on the east panel. The details are an image and description. Recently, I added relevant documents for that particular char, which will show on the bottom of the east panel. I created key listener's, so the client can quickly view the document by pressing a num key, but I also want to give them the ability to click on the button to launch a pdf view and see the contents of the document.
I'd use a JList to hold the list of selectable information on the left, and would react to it with a ListSelectionListener. In the listener, I'd change the related displayed information. I also avoid using KeyListeners with Swing but instead gravitate towards Key Bindings as they're more flexible and less rigid regarding focus.
Regarding
Since every char has different related docs and different number of docs, I repainted the buttons every time, to reflect the amount of related docs and the appropriate titles for the docs. This is where the repaint is acting strange. You gave me a good explanation of what's going wrong, but I don't know how to give the client access to the docs now, aside from painting a description of the doc along with the hot key needed to launch it. Does that make sense?
I'm not sure what you're doing here or what you're trying to do.
Since every char has different related docs and different number of docs, I repainted the buttons every time, to reflect the amount of related docs and the appropriate titles for the docs. This is where the repaint is acting strange. You gave me a good explanation of what's going wrong, but I don't know how to give the client access to the docs now, aside from painting a description of the doc along with the hot key needed to launch it. Does that make sense?
So rather then "painting" the buttons, why not just change there text (setText(...)).
When a user selects a "char". You are going to need to rebuild portions of your screen. Change the list model (as suggest above) and remove/add any buttons you need on the document container.

how to start, developing swing based application with few panels with next buttons for each

I'm new to java.I'm creating a swing based UI. I've created 2 frames, each one in separate .java file inside same package.
These two frames represents 2 screens (panels) of application. When Next button in first frame is clicked, it should move to second frame.
When I checked, these two classes are having main method, I think it should be correct way for creating applications. there should be only one main method.
When Next is clicked, I'm trying to make setVisible(false) for main panel of first frame and setVisible(true) for main panel of second frame. But this cannot be done, since the panels within a class are private. Any resolution for the above problem?
As I'm beginner, Can somebody suggest me in how to start up with these kind of applications? what are the guidelines that need to be followed? And please help me in finding documentation related to starting up with the development of such applications.
After going through the answers, My comments are:
I used the following code to go to next panel from first panel, but didn't worked.
private void gotoNextPanel(){
// jPanelFirstScreen.setVisible(false);
JPanelSecondScreen jpanelSecondScreen= new JPanelSecondScreen();
jpanelSecondScreen.setVisible(true);
UpgradeUtilityGUI upgradeUtilityGUI = new UpgradeUtilityGUI();
upgradeUtilityGUI.removeAll();
validate();
repaint();
// upgradeUtilityGUI.add(jpanelSecondScreen);
upgradeUtilityGUI.getContentPane().add(jpanelSecondScreen, "card2");
jpanelSecondScreen.setVisible(true);
validate();
repaint();
}
I'm using netbeans, and 've added two panels to the cardlayout of frame. And when I use the above code to change panels, Nothing is happening, the first panel is still appearing. Can somebody tell me, how to write code for moving from one panel to another when both the panels 've been added to cardlayout of jFrame ?
Use a CardLayout, as shown here (and one frame) as mentioned by others.
When Next is clicked, I'm trying to make setVisible(false) for main panel of first frame and setVisible(true) for main panel of second frame. But this cannot be done, since the panels within a class are private. Any resolution for the above problem?
Make the panels public access level and they will be available from other packages.
One problem in that code snippet is implied by the line:
UpgradeUtilityGUI upgradeUtilityGUI = new UpgradeUtilityGUI();
It goes out of scope before ever being added to a container. Also, their should be no need to remove anything when adding a new card to the layout, and no need to call repaint().
If your application is as simple as having only two panels you shouldn't create two JFrames. You should create a JFrame with two JPanel each of them contains the neccessary information for you. If you are ready with your first panel you can call setVisible(false) on it, and call setVisible(true) on the 2nd frame. It is the one of the most easy-to-understand solution.
But, it only depends on you if it is good for you or you would like to use some more detailed solution.
Don't use two or more JFrames, nor with separated and compiled Jar files, this is road to the hell, better would be look at CardLayout,
What you should do is have a single JFrame for the application, then you add and remove JPanels as you want to move between screens.
Each of your JPanels should basically have the following...
1. A JButton called "Next"
2. A ButtonListener for each button, that tells the JFrame to load panel2, panel3, etc.
As part of the ButtonListener, you basically just want to call something like JFrame.removeAll() to remove the existing panel, then JFrame.add(JPanel) to add the next panel.
By having 1 JFrame, you also only have 1 main() method.

How do I dynamically add Panels to other panels at runtime in Java?

I'm trying to get into java again (it's been a few years). I never really did any GUI coding in java. I've been using Netbeans to get started with this.
When using winforms in C# at work I use a usercontrols to build parts of my UI and add them to forms dynamically.
I've been trying to use JPanels like usercontrols in C#. I created a JPanel form called BlurbEditor. This has a few simple controls on it. I am trying to add it to another panel at run time on a button event.
Here is the code that I thought would work:
mainPanel.add(new BlurbEditor());
mainPanel.revalidate();
//I've also tried all possible combinations of these too
//mainPanel.repaint();
//mainPanel.validate();
This unfortunately is not working. What am I doing wrong?
I figured it out. The comments under the accepted answer here explain it:
Dynamically added JTable not displaying
Basically I just added the following before the mainPanel.add()
mainPanel.setLayout(new java.awt.BorderLayout());
Swing/AWT components generally have to have a layout before you add things to them - otherwise the UI won't know where to place the subcomponents.
BFreeman has suggested BorderLayout which is one of the easiest ones to use and allows you to 'glue' things to the top, bottom, left, right or center of the parent.
There are others such as FlowLayout which is like a textarea - it adds components left-to-right at the top of the parent and wraps onto a new row when it gets to the end.
The GridBagLayout which has always been notorious for being impossible to figure out, but does give you nearly all the control you would need. A bit like those HTML tables we used to see with bizarre combinations of rowspan, colspan, width and height attributes - which never seemed to look quite how you wanted them.
I was dealing with similar issue, I wanted to change the panel contained in a panel on runtime
After some testing, retesting and a lot of failing my pseudo-algorithm is this:
parentPanel : contains the panel we want to remove
childPanel : panel we want to switch
parentPanelLayout : the layout of parentPanel
editParentLayout() : builds parentPanel with different childPanel and NEW parentPanelLayout every time
parentPanel.remove(childPanel);
editParentLayout();
parentPanel.revalidate();
parentPanel.repaint();
As with all swing code, don't forget to call any gui update within event dispatch thread. See this for why you must do updates like this
// Do long running calculations and other stuff outside the event dispatch thread
while (! finished )
calculate();
SwingUtilities.invokeLater(new Runnable(){
public void run() {
// update gui here
}
}
mainPanel.add(new BlurbEditor());
mainPanel.validate();
mainPanel.repaint();
Try mainPanel.invalidate() and then if necessary, mainPanel.validate(). It also might be worth checking that you're doing this all in the event dispatch thread, otherwise your results will be spotty and (generally) non-deterministic.

Categories

Resources