Say I have n numbered components, e.g. n jPanels called panel1, panel2, ..., paneln, that were created using Netbeans' GUI Builder. As far as I'm aware the GUI Builder doesn't allow me to store components in an array when creating them, which means if I wanted to modify them during execution I'd have to do something like
jPanel[] panels = new jPanel[n];
panels[1] = panel1;
panels[2] = panel2;
.
.
.
panels[n] = paneln;
for(int i = 0; i < n; i++) {
//Do stuff with panels[i]
}
Is there some other way to do this without having to drop the Builder and create the interface from scratch?
Add this in your code:
List<JPanel> myPanels = new ArrayList<>();
private JPanel getNewPanel()
{
JPanel panel=new JPanel();
myPanels.add(panel);
return panel;
}
Then in the Netbeans GUI builder:
Using ctrl-click select all the panels you want to access via
myPanels
In the Code tab of the Properties window, set the Custom Creation Code to: getNewPanel();
Related
I'm a beginner in GUI.
Is there a quick way of setting the same JButton/Image to multiple locations within the GUI? For better clarification, if I want to use this JButton 10 times at different locations in my GUI, would I have to create a new JButton(new ImageIcon...) 10 times?
The buttons don't have to lead to anything, this is just for show.
JButton jb = new JButton(new ImageIcon("myImage.png"));
jb.setLocation(10,10);
jb.setSize(40, 40);
getContentPane().add(jb);
The short answer is, yes, you will need multiple instances of JButton.
You can use an Action which can be applied to multiple instance of a button (the same instance of Action). The Action class carries properties which will be used to configure the buttons, such as text and icon properties.
A component (like JButton) can only reside within in a single container, therefore, you will need multiple instances of JButton.
Take a look at How to Use Actions and How to Use Buttons, Check Boxes, and Radio Buttons for more details...
Generally, you should avoid using setLocation and setSize and rely more on the use of layout managers, but you've not provided enough context to say if this useful to you or not.
Yes, you need to create a Jbutton object for each desired instance.
Since you have so many JButton that are all similar, I suggest that you declare an array JButton[] buttons = new JButton[10]; and use a for loop to create each individual button and set their attributes.
If it is just for a show, I would do the following to show the 10 button in a row:
int buttonHeight = 10;
int buttonWidth = 10;
for (int i = 0; i < 10; i++) {
JButton button = new Button("Button " + i);
button.setSize(buttonWidth, buttonHeight);
button.setLocation(10 + i * buttonWidth, 10);
getContentPane().add(button);
}
import java.util.Scanner;
import javax.swing.*;
import java.awt.*;
class PROB4_CHAL1 extends JFrame
{
JButton b[]=new JButton[10];
public PROB4_CHAL1()
{
setLayout(null);
setVisible(true);
setSize(100,100);
for(int i=0;i<10;i++)
{
b[i]=new JButton(""+i);// or b[i]=new JButton(new ImageIcon("path"));
b[i].setBounds(i*10,i*20,50,20);
add(b[i]);
}
}
public static void main(String[] args)
{
new PROB4_CHAL1();
}
}
You can Create array of 'JButton [10]' .
I'm writing a program that takes in some equations from the user. I want each constant to be entered in a JTextField, with each separated by a JTextArea (saying +x0, +x1, etc.). However, I can't quite get the formatting to work, and I'm not sure why. Here's the relevant code:
JTextField[][] dataTextFields = new JTextField[a+1][b+1];
JTextArea[][] dataLabels = new JTextArea[a][b+1];
for (int i = 0; i < a+1; i++)
{
for (int j = 0; j < b+1; j++)
{
dataTextFields[i][j] = new JTextField(10);
dataTextFields[i][j].setLocation(5+70*i, 10+30*j);
dataTextFields[i][j].setSize(40,35);
dataEntryPanel.add(dataTextFields[i][j]);
if (i < a)
{
String build = "x" + Integer.toString(i) + "+";
dataLabels[i][j] = new JTextArea(build);
dataLabels[i][j].setBackground(dataEntryPanel.getBackground());
dataLabels[i][j].setBounds(45+70*i,20+30*j,29,30);
dataEntryPanel.add(dataLabels[i][j]);
}
}
}
This creates JTextFields with JTextAreas 0f "+xi" in between them. However, when I run the applet, it looks like this:
I can click on the labels and bring them to the foreground, it seems, resulting in this:
I'd like for the labels to be visible without any effort from the user, obviously. Does JTextArea have some attribute that can be changed to bring this to the foreground? I'd really prefer not to add any more UI elements (panels, containers, etc). Thanks!
I would layout the container using GridBagLayout. GridBagLayout works a lot like HTML tables, where you have different cells, which grow in height and width to try and accommodate the content most effectively. For your particular layout, something like this would work:
public class SwingTest extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run () {
new SwingTest().setVisible(true);
}
});
}
public SwingTest () {
super("Swing Test");
JPanel contentPane = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy = 0;
contentPane.add(createJTextField(), gbc.clone());
contentPane.add(new JLabel("x0+"), gbc.clone());
contentPane.add(createJTextField(), gbc.clone());
// go to next line
gbc.gridy++;
contentPane.add(createJTextField(), gbc.clone());
contentPane.add(new JLabel("x0+"), gbc.clone());
contentPane.add(createJTextField(), gbc.clone());
setContentPane(contentPane);
pack();
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
}
private JTextField createJTextField () {
JTextField textField = new JTextField(4);
textField.setMinimumSize(textField.getPreferredSize());
return textField;
}
}
GridBagLayout is the most complicated (but flexible) of the layouts, and requires many parameters to configure. There are simpler ones, like FlowLayout, BorderLayout, GridLayout, etc, that can be used in conjunction with one another to achieve complex layouts, as well.
In the Swing Tutorial, there is a very good section on Laying Out Components. If you plan on spending any significant amount of time on building Swing GUI's, it may be worth the read.
Note, that there is one strange caveat with GridBagLayout: if you are going to use a JTextField in a GridBagLayout, there is one silly issue (described here) that causes them to render at their minimum sizes if they can't be rendered at their preferred sizes (which causes them to show up as tiny slits). To overcome this, I specify the number of columns on my JTextField constructor so that the minimum is something reasonable, and then set the minimum size to the preferred size.
I have this code, and it makes a JPanel and adds it to a JScrollPanel. It works fine, but when I try to add a second JPanel it removes the first one and adds the second one. I would like to be able to place JPanels on top of JPanels, how can I do that?
// Location of an image:
String file = wfc.getSelectedFile().getPath();
// Creates images from different types:
ImageHandler image = new ImageHandler();
BufferedImage imageData = image.imageData(file);
// Extends JPanel, Layer is a JPanel
Layer layer = new Layer(image.width(), image.height());
layer.setImage(imageData);
layer.setSizeFromLoaded();
// A list of all the JPanels added
Layers.set(Layers.layers.size(), layer);
// Adds a JPanel to the JScrollPanel
imagePane.getViewport().add(layer, BorderLayout.CENTER);
Here is the full method, it opens a file browser, then when the image is selected it runs the above code
private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {
WebFileChooser wfc = null;
if(wfc == null){
wfc = new WebFileChooser(this, "Open an Image");
wfc.setSelectionMode(SelectionMode.SINGLE_SELECTION);
wfc.setAvailableFilter(GlobalConstants.IMAGES_AND_FOLDERS_FILTER);
wfc.setChooseFilter(GlobalConstants.IMAGES_FILTER);
wfc.setCurrentDirectory("/Users");
}
wfc.setVisible(true);
if(wfc.getResult() == StyleConstants.OK_OPTION){
String file = wfc.getSelectedFile().getPath();
ImageHandler image = new ImageHandler();
BufferedImage imageData = image.imageData(file);
Layer layer = new Layer(image.width(), image.height());
layer.setImage(imageData);
layer.setSizeFromLoaded();
Layers.set(Layers.layers.size(), layer);
imagePane.getViewport().add(layer, BorderLayout.CENTER);
}
}
You may wish to consider placing you panels into a single master panel which is using a CardLayout.
This will allow you to easily switch between panels giving the illusion of layered panels without the hassle of doing it manually.
Something like...
JPanel master = new JPanel(new CardLayout());
master.add(new ChildPane()); // Or what ever child you want to add
master.add(new ChildPane()); // Or what ever child you want to add
//...
JScrollPane scrollPane = new JScrollPane(master);
I used Zove Games suggestion and placed it within a JLayerdPanel, and it works perfectly!
You can put both of the panels inside of one JPanel, and then put that in the JScrollPane.
I want to create a JTabbedPane, add a JPanel to everyone and then add something to the JPanel:
private void initTabbedPane(JTabbedPane tp)
{
System.out.println("FestplattenreinigerGraphicalUserInterface::initTabbedPane()");
// Init Tab-Names
Vector<String> tabNames = new Vector<String>();
tabNames.addElement("Startseite");
tabNames.addElement("Konfiguration");
tabNames.addElement("Hilfe");
// Init Tabs
tp = new JTabbedPane();
JPanel tmpPanel;
for(int i = 0; i < tabNames.size(); i++)
{
tmpPanel = new JPanel();
tp.addTab(tabNames.elementAt(i), tmpPanel);
}
tp.setFont(new Font("Calibri", Font.BOLD, 11));
initPanelsInTabbedPane(tp);
this.getContentPane().add(tp, BorderLayout.CENTER);
}
private void initPanelsInTabbedPane(JTabbedPane tp)
{
System.out.println("FestplattenreinigerGraphicalUserInterface::initPanelsInTabbedPane()");
tp.getComponentAt(0).add(new JButton("HELLOSTUPIDJAVAIHATEU"));
}
Well it says:
incompatible types
found : java.awt.Component
required: javax.swing.JPanel
JPanel p = tp.getComponentAt(0);
But my book says that with, Component getComponentAt(int index), i can access it's content and i remember that JButton is a Component right? So wth?
If you take a look at Javadoc, you'll see that, indeed, JTabbedPane#getComponentAt(index) returns a Component. However, if you're sure it's a JPanel (which is more or less the case when accessing tabs of a JTabbedPane), you can always cast it :
((JPanel) tp.getComponentAt(0)).add(new JButton("come on, Java is nice enough, no ?"));
Or, even better if you know some things about Swing
((JCompoonent) tp.getComponentAt(0)).add(new JButton("No, Java and Swing positively rock hard awesome !"));
indeed, JPanel is a subclass of JComponent, which is
the root class of all Swing components
an awt Container
I have a LinkedList of Components, each of which I would like to add into two different JTabbedPanes. For some reason, Swing is only letting me put each component into one or the other. The code I'm using is the following:
/* The two tab panes */
JTabbedPane leftTabs = new JTabbedPane();
JTabbedPane rightTabs = new JTabbedPane();
for (int i=0; i<tabPanes.size(); i++) {
rightTabs.add(tabPanes.get(i));
leftTabs.add(tabPanes.get(i));
}
Whichever add call I put last is the one that works; if I add to leftTabs last, then rightTabs ends up empty, and vice-versa.
Any ideas on how to get this working? Thanks!
A component can only have a single parent, so you can't add it to two different tabs.
However the model of the component can be shared. For example:
JTextField textField1 = new JTextField();
JTextField textField2 = new JTextField();
textField2.setDocument( textField1.getDocument() );
So somehow you to figure out how to share models, not the components.