Adding to JPanel in application - java

When a particular button is clicked I want another set of buttons to be added to the Panel, however at the moment when I do this, I can add them as many times as I want, I need this to be only possible once. Would the best way to do this be set the adding of the buttons and fields in a while loop?
if(e.getSource() == selectScript){
while(scriptB < 1 ){
imageID = new JTextField("INT");
imageDescription = new JTextField("imgDescription");
imagePath = new JTextField("imagePath");
manageImageTab.add(imageID);
manageImageTab.add(imageDescription);
manageImageTab.add(imagePath);
insertImage = new JButton("Add an Image");
insertImage.addActionListener(new dbaccess());
manageImageTab.add(insertImage);
manageImageTab.revalidate();
validate();
scriptB++;
}
}

Perhaps rather than add and remove the JButtons, you could add the buttons once at the code start, just don't make them visible until you need them, or perhaps better place them all on a JPanel that is not visible and then made visible when desired. Just don't forget to call revalidate() and repaint() on the container that holds the buttons and their panel.

If I understand you correctly, I would use a flag alreadyAdded that starts out false, gets set to true after the controls have been added, then don't allow it to add after that.

Related

Creating Buttons during runtime in Java

I want to add a number of Buttons to my Java application based on an array. Say if there are 10 objects in an array, I want to create 10 buttons. If I delete 2 objects in the array the buttons should also get deleted. I thought about 3 things to go on about this problem.
A for loop - but I think the buttons would just exist inside the loop and also I would not know how to name the buttons (the variable name not the label).
A Thread
A seperate class
I have no idea how I would do that though.
Can I actually name variables through loops?
Are any of my ideas practicable?
If you add a button to a JPanel it will survive outside the for loop, so don't worry about it. Create a JPanel just for your buttons and keep track of those you add using an ArrayList<JButton>, so you'll be able to delete them as you need. To delete them from the panel, refer to this answer. Remember to repaint (=refresh) the JPanel.
JButton button1 = ...;
// Add it to the JPanel
// https://stackoverflow.com/questions/37635561/how-to-add-components-into-a-jpanel
ArrayList<JButton> buttons = new ArrayList<>();
buttons.add(button1);
// Other stuff...
// It's time to get rid of the button
JButton theButtonIWantToRemove = buttons.get(0);
buttons.remove(0);
//Get the components in the panel
Component[] componentList = panel.getComponents();
//Loop through the components
for(Component c : componentList){
//Find the components you want to remove
if(c == theButtonIWantToRemove){
//Remove it
panel.remove(c);
}
}
//IMPORTANT
panel.revalidate();
panel.repaint();

Refreshing JLabel - Java

I have some problems with JLabels and Frames..
I have the following code:
list.addListSelectionListener(
new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
//System.out.println(e.getFirstIndex());
String selectedFile = list.getSelectedValue().toString();
System.out.println("Selected file " + selectedFile);
JLabel label;
ImageIcon icon = new ImageIcon("C:\\Users\\danie\\Pictures\\" + selectedFile);
// frame.setSize(1047, 680);
label = new JLabel(icon);
//label.setSize(100,100);
frame.getContentPane().add(label, BorderLayout.CENTER);
frame.revalidate();
frame.repaint();
}
});
I want to refresh the label in the center of the borderlayout if a item in a JList is selected. But with this code, the old image is futher displayed and the new image is only drawed behind the existing image.
Could anyone help me? :)
First you are creating a new JLabel instance instead of working on the existing one. What you actually want to do is:
labe.setIcon(icon);
This will automatically refresh the element.
Suggestions:
Don't create a new JLabel, give it an ImageIcon and expect the existing JLabel to change. The two JLabels, the original one and the one created here, are two completely different objects, and changing the state of one (the icon it's displaying) will not magically change the state of the other.
Do make sure that the original JLabel has an instance variable in the class (not in your listener class), a field, refer to it, and then in your listener code, change the icon displayed in that JLabel by calling its setIcon(...) method
No need to call revalidate() or repaint() here as this should be done if you change components held within a container, such as if you removed the original JLabel from the JFrame's contentPane and swapped in a new one. Note that I do not recommend that you do this as it is over-complicating what should be a simple thing -- swapping icons.
To simplify things, I suggest that you read all your images in at program startup, create ImageIcons at that time, and then put them into an array or collection (such as an ArrayList<Icon> or a HashMap<String, Icon>), and then in your listener code, extract the correct icon, and put it into the existing JLabel.
You are not using the same JLabel it seems. You should alter the label you already have, not create a new one.

Switch between multiple JFrames

I'm relatively new to Java and I'm trying to make some kind of quiz. I created 3 JFrames, all in the same package. On my main frame, there are two buttons (one for the english version and the other one for the german version). I want to switch JFrames after pressing these buttons (so that I can, by pressing "English", see and interact with my english quiz frame). Looking it up didn't help me the slightest, because I'm not really experienced with it. Is it even possible to do it like this? If not, how could I do it?
The standard approach is to use the Card Layout, which allows you to use the same JFrame as you populate it with different things at different points in your application. So initially, your JFrame would show the loading screen, then the user presses a button and you load a new set of components without discarding the current JFrame you have. In some cases, you might also need to make some size adjustments.
It is difficult to say without seeing any code, but usually, what is done is that you do something like so:
new Frame(args);
this.dispose();
The code above assumes that the constructor of Frame takes care of launching and making the components visible. The this.dispose(); disposes of the current JFrame (assuming your class extends JFrame).
You have two buttons in your frame 1 right? So first, double click the button which says "English". Lets say the variable name for that button is jButton1. Inside that button type this.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
this.dispose();
EnglishFrame eng = new EnglishFrame();
eng.setVisible(true);
}
Then double click the other button which says "German" (jButton2). Inside that type this.
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
this.dispose();
GermanFrame german = new GermanFrame();
german.setVisible(true);
}
this.dispose() - This will cause the jFrame window to close
Then you create an object of the other two forms. (In your case the form for English and Germany)
.setVisible(true) - This will show you the form.
Create a single Jframe window. After that create JPanels with all the compenents such as buttons, textfields and labels you want. Make sure the panel is the same size as your Jframe. Panel's work about the same as JFrame's, code wise.
This code will stitch everything together for you:
panel.setSize(Jframe.getSize()) //That wont
panel.add(button); //Just remember you need to add more code to position the buttons correctly.
//If you using netbeans builder:
//You just have to use this one line in the constructor/intialiser method
frame.add(panel); //This will add the panel to the Jframe/Window
//No need to add extra code for positioning.
If you want to swap between the panels. In the button press method, use this
frame.setContentPane(panel); //panel = panel you want to change too.
frame.repaint(); //Ensures that the frame swaps to the next panel and doesn't get stuck.
frame.revalidate(); //Ensures that the frame swaps to the next panel and doesn't get stuck.
When you first start the java application you have to set the content pane or else it will appear as a blank window.
frame.setContentPane(panel); //Starting Panel
frame.setVisible(true); //Make the frame visible
Sorry if the explanation is bad, I don't have enough time to explain it fully.

Delete element from GridBagLayout

how can I delete element from GridBagElement ?
http://i.stack.imgur.com/1BsDW.jpg
I want to remove the selected item by clicking on the button.
How can I send the name of the selected item as a parameter to the action button?
First, you don't delete from GridBagLayout. With swing you add Components to a Container, and you remove them from a Container.
http://docs.oracle.com/javase/6/docs/api/java/awt/Container.html#remove%28java.awt.Component%29
To select the Green Panel you can Register an ActionListener or MouseListener for this Panel.
The MouseListener delivers the MouseEvent.
The MouseEvent can get you the Source with getSource, which is the green Panel.
And that panel can be removed.
A simple example snippet:
final JPanel mainPanel = new JPanel();
JPanel greenPanel = new JPanel();
greenPanel.addActionListener(new ActionListener(){
#Override
public void ActionPerformed(ActionEvent e){
int answer = JOptionPane.showConfirmDialog(null, "Delete?");
if(answer == JOptionPane.YES_OPTION){
mainPanel.remove(e.getSource());
}
}
});
mainPanel.add(greenPanel);
You will want to establish some kind of contract between things like buttons and other controls and your view.
Things that want to modify the view should not be able to do anything you don't want them to (like change the layout for instance).
I'd recommend creating a simple interface which provided access to the operations you want external controls to have access to (like adding, editing, removing). This you would pass to your controls, there by restricting what the controls can actually do and not exposing unnecessary functionality to them (you wouldn't one of them to remove you main panel ;)).
When you want to remove a selected task, you click the appropriate button, it calls the appropriate "remove" method on your model.
You implementation would then find the selected item (which I assume you either maintain a reference to or have some means to find) and simply remove it from it's parent container.

Swing controls work under Java 6, not under Java 7

I'm performing maintenance on an existing application. The feature I'm working on used to work when compiled under Java 6, but doesn't under Java 7. I'll try to be brief.
The app has a huge JTabbedPane that composes almost the entire UI. The JTabbedPane contains a number of JPanels. Each JPanel, in turn, contains an obscene number of JComponents. The user can enter values into the controls, but if--for some reason--they want to clear out all their changes, they can select an option to "reset" the panel. The way the responsible method works is it removes the JPanel, recreates a new one of the exact same class (they all inherit from JPanel) and re-inserts it at the same index into the JTabbedPane. Simple, right?
But what actually happens is it switches to the next JPanel tab in the JTabbedPane and then a number of controls from the new panel show up overlapping the controls in the next panel. So, for example, if I had panel0 selected and wanted to reset it, it would show panel1 as selected and a whole bunch of panel0's components overlapping it.
It gets even weirder. No other tabs can be selected after this happens. It's like the UI freezes. The user has to select the current tab (i.e. panel1) by clicking its tab on top (which is strange because it's already selected). Then they can go to other tabs and everything acts as it should. But if they don't know the workaround, it's rather frightening. And it's just plain wrong. Reseting the panel should just show the same panel with all of the controls blank.
Here is what is done, in pseudo-code:
Get the current panel
Create a new instance of it
Remove current panel
Insert new instance
Revalidate & repaint
Set the selected index of the panel
Here is the actual code:
public void resetCurrentTab( int currentTabIndex ) {
// tried using m_tabbedPane.getTabComponentAt( currentTabIndex), but that returns null
JPanel curTab = (JPanel)m_tabbedPane.getSelectedComponent();
if( curTab == null )
return;
String curTabName = curTab.getName().trim();
// create new instance of panel
JPanel newPanel = null;
try {
newPanel = curTab.getClass().newInstance();
} catch (InstantiationException e) {
log.equals("Could not reset tab... tab " + curTabName + " creation failed.");
return;
} catch (IllegalAccessException e) {
log.equals("Could not reset tab... tab " + curTabName + " creation failed.");
return;
}
if( newPanel != null ) {
m_tabbedPane.remove( currentTabIndex );
m_tabbedPane.insertTab( newPanel.getName(), null, newPanel, null, currentTabIndex );
newPanel.setVisible( true );
}
m_tabbedPane.revalidate();
m_tabbedPane.repaint();
m_tabbedPane.setSelectedIndex( currentTabIndex );
}
Like I said, this works compiled under Java 6. Under Java 7, weirdness happens. I tried all the obvious things, like changing the order of the calls to revalidate(), repaint() and setSelectedIndex(), but that doesn't change the behavior. I also tried just taking out and re-adding the same JPanel just to see what would happen. I don't get the overlapping controls weirdness, but it does go and select the next JPanel (tab) in the tabbed control.
tl;dr
A feature that runs fine compiled under Java 6 doesn't work compiled under Java 7.
Any ideas?
EDIT: I traced the problem back to something else entirely. Before the user resets the tab, a method pops up a JOptionPane asking if they're sure they want to do it. It's just using the simple YES/NO version of .showConfirmDialog(). If I remove the dialog, the feature works perfectly. If I use the dialog, I get the screwy behavior.
int response = JOptionPane
.showConfirmDialog(
currentTab,
confirmMsg,
"Reload the '" + curTabName + "' Tab",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE );
if( response == JOptionPane.YES_OPTION )
// return a value indicating to reset the panel
I tried a few different values for the first parameter, but none alter the behavior. As you can see, the dialog falls out of scope long before the resetting occurs. Still don't know why this worked under Java 6 and not 7.
Thanks for all the suggestions.
I fixed this in an unusual way, but it's an unusual bug. I removed the Panel (called curTab in the code above) in the method was previously done, then set a flag. The TabbedPane (I had to create my own, inherited from JTabbedPane) looks for the flag in a custom Paint() method. I don't do any custom painting, but in the method, I allocate the new Panel and insert it into the TabbedPane at the index the old one was removed from. Then I clear all flags and clean up everything.
Like I said, it's an unusual fix, but it's the only way I tried I could avoid the visual and functionality glitch.

Categories

Resources