In Food Tab, I want to achieve this
But I only able to get this
How can I increase the width of the JTextField which are in Food Tab ? Below is my code
public class FoodOrdering {
static private JFrame frame;
static private JTextField textField;
static private GridBagConstraints gbc;
static private JLabel[] foodLabel;
static private JLabel[] labels;
static private JTextField[] qtyField;
static private JLabel[] foodImage;
static private File[] file;
private static final int ELEMENTS = 9;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
FoodOrdering window = new FoodOrdering();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*
* #throws IOException
*/
public FoodOrdering() throws IOException {
initialize();
}
/**
* Initialize the contents of the frame.
*
* #throws IOException
*/
static void initialize() throws IOException {
frame = new JFrame();
frame.setBounds(100, 100, 700, 550);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.setLocationRelativeTo(null);
JLabel lblFoodOrdered = new JLabel("Food Ordered");
lblFoodOrdered.setBounds(529, 11, 81, 14);
frame.getContentPane().add(lblFoodOrdered);
TextArea textArea = new TextArea();
textArea.setBounds(462, 31, 199, 275);
frame.getContentPane().add(textArea);
JLabel lblTotal = new JLabel("Total : ");
lblTotal.setBounds(519, 315, 46, 14);
frame.getContentPane().add(lblTotal);
textField = new JTextField();
textField.setBounds(575, 312, 86, 20);
frame.getContentPane().add(textField);
textField.setColumns(10);
JButton btnOrder = new JButton("Order");
btnOrder.setBounds(521, 352, 89, 23);
frame.getContentPane().add(btnOrder);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
addIt(tabbedPane, "Foods");
addIt1(tabbedPane, "Drinks");
addIt1(tabbedPane, "Desserts");
tabbedPane.setBounds(23, 11, 400, 450);
frame.getContentPane().add(tabbedPane);
frame.setVisible(true);
}
static void addIt1(JTabbedPane tabbedPane, String text) {
JLabel label = new JLabel(text);
JButton button = new JButton(text);
JPanel panel = new JPanel();
panel.add(label);
panel.add(button);
tabbedPane.addTab(text, panel);
}
static void addIt(JTabbedPane tabbedPane, String text) throws IOException {
JPanel panel = new JPanel(new GridBagLayout());
gbc = new GridBagConstraints();
gbc.insets = new Insets(1, 1, 1, 1);
foodImage = new JLabel[ELEMENTS];
foodLabel = new JLabel[ELEMENTS];
labels = new JLabel[ELEMENTS];
qtyField = new JTextField[ELEMENTS];
file = new File[ELEMENTS];
try {
file[0] = new File("C:\\Users\\tony\\Desktop\\MedSalad.png");
file[1] = new File("C:\\Users\\tony\\Desktop\\JapanesePanNoodles.png");
file[2] = new File("C:\\Users\\tony\\Desktop\\Spaghetti.png");
file[3] = new File("C:\\Users\\tony\\Desktop\\PadThai.png");
file[4] = new File("C:\\Users\\tony\\Desktop\\RamenNoodles.png");
file[5] = new File("C:\\Users\\tony\\Desktop\\SpaghettiAndMeatBalls.png");
file[6] = new File("C:\\Users\\tony\\Desktop\\chickenRice.jpg");
file[7] = new File("C:\\Users\\tony\\Desktop\\thaiFood.jpeg");
file[8] = new File("C:\\Users\\tony\\Desktop\\vietnamFood.jpg");
foodLabel[0] = new JLabel("Salad");
foodLabel[1] = new JLabel("Japanese Noodles");
foodLabel[2] = new JLabel("Spaghetti");
foodLabel[3] = new JLabel("Spaghetti Meat Balls");
foodLabel[4] = new JLabel("Noodles");
foodLabel[5] = new JLabel("Kids Spaghetti");
foodLabel[6] = new JLabel("Chicken Rice");
foodLabel[7] = new JLabel("Thai Food");
foodLabel[8] = new JLabel("Vietnam Food");
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < ELEMENTS; i++) {
Image image = ImageIO.read(file[i]);
Image imageScaled = image.getScaledInstance(80, 95, Image.SCALE_SMOOTH);
ImageIcon imageIcon = new ImageIcon(imageScaled);
qtyField[i] = new JTextField(3);
foodImage[i] = new JLabel(imageIcon);
}
gbc.gridx = 0;
for (int i = 0; i < ELEMENTS; i++) {
if (i % 3 == 0) {
gbc.gridy += 2;
gbc.gridx = 0;
}
panel.add(foodImage[i], gbc);
gbc.gridy++;
panel.add(foodLabel[i], gbc);
gbc.gridy--;
gbc.gridx++;
panel.add(qtyField[i], gbc);
gbc.gridx++;
tabbedPane.addTab(text, panel);
}
}
public void setVisible(boolean b) throws IOException {
}
}
The JTextfield objects are so narrow because of a very old "bug" in GridBagLayout which causes it to ignore the preferred size of its contents.
There are several possible ways to work-around this bug:
Create a class called PreferredGridBagLayout as explained in the link and use that instead of GridBagLayout.
Set the minimum size of each of your qtyField instances with qtyField[i].setMinimumSize(qtyField[i].getPreferredSize()).
Create subclasses of JTextField which override the method getMinimumSize() to return the same value as getPreferredSize(), or some other reasonable minimum size.
Because this problem is so common when using GridBagLayout, solution #1 is the easiest in the long term.
Afterwards, you'll need to make your tabbedPane object a little wider, or switch to a layout manager in the main panel that automatically determines the size of the tabbed pane.
There are multiple things that could be improved in your code. Creating good layouts in Swing is not easy, and you will need much more work to make a pretty layout. But this will solve your problem with collapsing text fields.
This problem simply can be solved by setting the
qtyField[i].setMinimumSize(new Dimension(33,20));
function. The reason for setting minimum size is that the GridBagLayout dont have enough space to arrange all those components properly so it only takes the minimum size of the empty textField.
Just add the code after the line
qtyField[i] = new JTextField(3);
and you will be also needed to increase the width of tabbedPane a little bit more to make the components(qtyField) visible
Instead of using null layout. use some other layout like border layout. Then use just one line:
frame.pack();
This will display all the components at their preferred sizes.
Just a coding practice: instead of setting bounds use panels to add components and then add these panels to a main panel.
Like use one different panel to add your Jlabel of food ordered, textarea, Jlabel for order and order button. And then add that panel to your main panel.
Hope you understand. :)
Related
I am trying to making a calculator.
Here the user can add multiple JTextFields to take his/her desired input with just one button click.
Now I want that the user will take the input in multiple JTextFields added by him and on clicking the Result button will show the sum of all. But I am always getting 0 as output.
Code:
public class Button extends JFrame {
private JPanel contentPane;
private JButton btnAdd;
private JButton btnResult;
private JTextField resultField;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Button frame = new Button();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Button() {
initComponents();
}
static JTextField field = null;
//static JTextField fields[] = new JTextField[10];
private static int y = 0;
ArrayList<String> arr = new ArrayList<String>();
int ans, sum = 0;
private void initComponents() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 527, 414);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
btnAdd = new JButton("Add");
btnAdd.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
field = new JTextField();
field.setBounds(45, y += 60, 284, 32);
field.setAlignmentX(Component.CENTER_ALIGNMENT);
contentPane.add(field);
contentPane.revalidate();
contentPane.repaint();
}
});
btnAdd.setBounds(170, 341, 89, 23);
contentPane.add(btnAdd);
btnResult = new JButton("Result");
btnResult.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < arr.size(); i++) {
arr.add(field.getText());
sum += Integer.parseInt(arr.get(i));
}
resultField.setText(String.valueOf(sum));
}
});
btnResult.setBounds(383, 306, 89, 23);
contentPane.add(btnResult);
resultField = new JTextField();
resultField.setBounds(361, 275, 129, 20);
contentPane.add(resultField);
resultField.setColumns(10);
}
}
Please help how can I find the correct output?
Suggestions:
Again, when you create a data-entry text field, add it to the GUI and add it to an ArrayList of the data entry field type.
Then in the result button's ActionListener, iterate through this list using a for loop.
Inside of the for loop, get the entry field, get its text (via .getText() if using a JTextField), parse it to number via Integer.parseInt(...), and add it to a sum variable that is initialized to 0 prior to the for loop. Then display the result after the loop.
Also,
Best to use JSpinners that use a SpinnerNumberModel such as JSpinner spinner = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1)); instead of JTextField for number entry. This will limit the user to entering numbers only, and won't allow non-numeric text entry, a danger inherent in your current design.
Having to add your entry fields by button may be an over-complication
But if it is necessary, then best to add the spinners (or text fields if you must) to a JPanel that uses a proper layout manager, such a new GridLayout(0, 1) (variable number of rows, 1 column) and then add that to a JScrollPane so that you can see as many fields as has been entered.
If using a JSpinner, then you don't even need a "calculate result" button, since if you add a ChangeListener to each JSpinner, you can calculate the result on the fly whenever a spinner has had its data changed.
e.g.,
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
#SuppressWarnings("serial")
public class Button2 extends JPanel {
private List<JSpinner> spinnerList = new ArrayList<>();
private JButton resultButton = new JButton("Result");
private JButton addEntryFieldBtn = new JButton("Add Entry Field");
private JTextField resultField = new JTextField(6);
private JPanel fieldPanel = new JPanel(new GridLayout(0, 1, 4, 4));
public Button2() {
resultField.setFocusable(false);
resultButton.addActionListener(e -> calcResult());
resultButton.setMnemonic(KeyEvent.VK_R);
addEntryFieldBtn.addActionListener(e -> addEntryField());
JPanel topPanel = new JPanel();
topPanel.add(addEntryFieldBtn);
topPanel.add(resultButton);
topPanel.add(new JLabel("Result:"));
topPanel.add(resultField);
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.add(fieldPanel, BorderLayout.PAGE_START);
JScrollPane scrollPane = new JScrollPane(centerPanel);
scrollPane.setPreferredSize(new Dimension(300, 300));
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(scrollPane);
}
private void calcResult() {
int sum = 0;
for (JSpinner spinner : spinnerList) {
sum += (int) spinner.getValue();
}
resultField.setText(String.valueOf(sum));
}
private void addEntryField() {
JSpinner spinner = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1));
spinner.addChangeListener(evt -> {
calcResult();
});
fieldPanel.add(spinner);
spinnerList.add(spinner);
revalidate();
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
Button2 mainPanel = new Button2();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
So I've got a custom JPanel which I use multiple instances of to fill a wrapper Panel inside a JScrollPane. The number of custom JPanel elements I use is dependent on the size of a list. The problem I'm running across is a part of my Custom JPanel has another invisible JPanel which expands when I click on it's parent. The behavior I'm trying to mimic is that of an accordian UI element. Before I was on this project I was primarily a webdev and while I have worked with Java a lot, I'm still relatively new to Swing.
Here is an example of the behavior - the scroll pane with all elements closed. (forgive me for the quick paint-job comments. I tried to emphasize what I see going wrong).
Next, is the image of the first element expanded - which unexpectedly expands all other elements.
It must be noted that I'm only targeting the first panel and setting the visibility, yet all other repeating panels length grows when I do this, but obviously the components inside stay invisible.
Finally, here is my final deired result:
Is there some sort of constraint in the JScrollPane that resizes it's child JPanel's components to retain the same height at all times? I can't seem to figure a way around this and I've played with all sorts of different wrappers and layouts, all to no avail.
Please let me know if anyone wants to see code snippets, but they'll have to be heavily redacted and stripped down due to the nature of the project.
Thanks,
Marek
PS: yes, I absolutely must use Swing.
Edit: Here is a static, quick and dirty, stripped down implementation of my code as suggested by Roddy of the Frozen Peas
ExampleScrollPane:
public class ExampleSrollPane extends JPanel {
private static ExampleSrollPane instance = null;
private JScrollPane contentScrollPanel = new JScrollPane();
private Vector<ExamplePanel> exPanels;
private JPanel wrapPanel = new JPanel();
public ExampleSrollPane() {
super();
this.setLayout(new BorderLayout());
this.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.white,
Color.white, new Color(115, 114, 105), new Color(165, 163, 151)));
exPanels = new Vector<ExamplePanel>();
init();
}
private void init() {
contentScrollPanel.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
contentScrollPanel.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
contentScrollPanel.setBorder(new CompoundBorder(new EmptyBorder(5, 5, 5, 5), new SoftBevelBorder(BevelBorder.LOWERED)));
this.add(contentScrollPanel, BorderLayout.CENTER);
initPanels();
}
public void initPanels() {
int numUnits = 15;
// Init one empty panel at least
if (numUnits == 0) numUnits = 15;
wrapPanel.setLayout(new GridLayout(numUnits, 1));
for (int i = 0; i < numUnits; i++) {
ExamplePanel exPan = new ExamplePanel(i);
exPanels.add(i, exPan);
wrapPanel.add(exPan);
}
contentScrollPanel.setPreferredSize(new Dimension(575, 100));
contentScrollPanel.getViewport().add(wrapPanel);
}
/**
* Method: viewPanel()
*
*/
private static void viewPanel() {
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.setLocationRelativeTo(null);
frame.add(getInstance());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setSize(new Dimension(600, 350));
frame.setAlwaysOnTop(true);
frame.setVisible(true);
}
public static ExampleSrollPane getInstance() {
if (instance == null) {
instance = new ExampleSrollPane();
}
return instance;
}
/**
* The main method.
*
* #param args the arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
viewPanel();
}
});
}
}
It's here in the showHideTable method which creates the problem.
ExamplePanel (my custom JPanel):
public class ExamplePanel extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private static final Border STAT_BORDER = BorderFactory.createBevelBorder(BevelBorder.LOWERED, Color.white,
Color.white, new Color(115, 114, 105), new Color(165, 163, 151));
public static final EmptyBorder PAD_BORDER = new EmptyBorder(10, 10, 10, 10);
public int indx;
private JLabel unitLabel;
private JLabel statLabel;
private JLabel invLabel;
private JLabel targetLabel;
private JLabel timeLabel;
// Custom BasicArrowButton to expand/hide the "table"
private UnitToggleButton unitToggleButton;
// The expandable JPanel
public ExpanableTable elementTable;
private String id;
private String unitStatusString;
private String invStatusString;
private String targetString;
private String timeString;
public Color componentColor;
private JPanel topPanel = new JPanel();
public JPanel tablePanel = new JPanel();
public ExamplePanel(int index) {
super();
this.indx = index;
id = "Unit # 00000";
id = "Unit #00000";
unitStatusString = "PENDING";
invStatusString = "PENDING";
elementTable = new ExpanableTable();
targetString = "AZ501";
timeString = "11:18:27";
componentColor = this.getBackground();
init();
}
private void init() {
topPanel.setLayout(new GridBagLayout());
topPanel.setBorder(PAD_BORDER);
unitLabel = new JLabel(id); // TODO unit.getID();
statLabel = new JLabel(unitStatusString); // TODO: unit.getStatus();
invLabel = new JLabel(invStatusString); // TODO: unit.getInventoryStatus();
targetLabel = new JLabel(targetString);
timeLabel = new JLabel(timeString);
buildLabel(statLabel);
buildLabel(invLabel);
buildLabel(targetLabel);
buildLabel(timeLabel);
unitToggleButton = new UnitToggleButton(BasicArrowButton.EAST, indx);
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.FIRST_LINE_START;
gbc.fill = GridBagConstraints.FIRST_LINE_END;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = .1;
gbc.weighty = 1;
gbc.insets = new Insets(0, 0, 5, 0);
// Add toggle button far-left, row 1
topPanel.add(unitToggleButton, gbc);
// Add empty space far-left, row 2
gbc.gridy = 1;
topPanel.add(new JLabel(" "), gbc);
// Add unit label row 1 column 2
gbc.gridy = 0;
gbc.gridx = 1;
gbc.weightx = .3;
topPanel.add(unitLabel, gbc);
// Add Status label row 1 column 3
gbc.gridx = 2;
topPanel.add(statLabel, gbc);
// Add inventory label row 1 column 4
gbc.gridx = 3;
topPanel.add(invLabel, gbc);
// Add tasking label row 2 column 2
gbc.gridy = 1;
gbc.gridx = 1;
topPanel.add(new JLabel(" Tasking: "), gbc);
// Add target label row 2 column 3
gbc.gridx = 2;
topPanel.add(targetLabel, gbc);
// Add mission Label row 2 column 4
gbc.gridx = 3;
topPanel.add(timeLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gbc.weighty = 1;
gbc.weightx = 1;
gbc.gridwidth = 4;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(0, 0, 0, 0);
JSeparator sep = new JSeparator(JSeparator.HORIZONTAL);
topPanel.add(sep, gbc);
gbc.gridy = 3;
topPanel.add(elementTable, gbc);
revalidate();
this.setLayout(new BorderLayout());
this.add(topPanel, BorderLayout.NORTH);
this.add(tablePanel, BorderLayout.CENTER);
HSIUtils.setColoredBorder(tablePanel, Color.RED);
tablePanel.add(elementTable);
// Do NOT show the table on initialization
tablePanel.setVisible(false);
unitToggleButton.addActionListener(this);
}
/**
* Method: buildLabel()
*
* #param label
*/
private void buildLabel(JLabel label) {
label.setBorder(STAT_BORDER);
label.setMinimumSize(new Dimension(80, 20));
label.setPreferredSize(new Dimension(100, 25));
label.setOpaque(true);
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setBackground(componentColor);
}
private void showHideTable(boolean show) {
tablePanel.setVisible(!show);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == this.unitToggleButton) {
showHideTable(unitToggleButton.isExpanded());
}
}
}
ExpandableTable:
public class ExpanableTable extends JPanel {
public ExpanableTable () {
super();
this.setLayout(new BorderLayout());
add(new JButton("Test1"), BorderLayout.WEST);
add(new JButton("Test2"), BorderLayout.CENTER);
add(new JButton("Test3"), BorderLayout.EAST);
}
}
Basically I want to be able expand/show/resize each Panel inside the scroll pane independently of the others. As it currently stands, if I show a hidden Panel on one, the other panel's height grows to match but does not show the component. Very strange to me but could be my ignorance of certain Swing components and the constraints they contain.
Is there some sort of constraint in the JScrollPane that resizes it's child JPanel's components to retain the same height at all times?
A scroll pane doesn't resize anything. It only displays the component added to the scroll panes and add scroll bars when the preferred size of the component added is greater than the size of the scroll pane.
wrapPanel.setLayout(new GridLayout(numUnits, 1));
On the other hand when you use a GridLayout, then yes all components added to the grid will be resized to the size of the largest component.
So you don't want to use a GridLayout for the wrapper panel.
I would suggest you could use a GridBagLayout or a BoxLayout. As the panel.
Then I would suggest that for your expandable panel you use a BorderLayout. You add the part that is always visible to the CENTER and the expandable part to the PAGE_END. Then when you want to make the panel expand you just change the visibility of the component in the PAGE_END.
Then the layout managers will do all the work recalculating the proper size of the all the panels.
sorry for the simple question, but I'm really new to this and can't really find an answer. I'm confused on how to add two (or more) JButtons. I can't seem to get both to show, only one ever shows, which is the "Division" one.
My most recent attempt is below. How can I get both buttons to show at the button of the window?
public class Calculator implements ActionListener {
private JFrame frame;
private JTextField xfield, yfield;
private JLabel result;
private JButton subtractButton;
private JButton divideButton;
private JPanel xpanel;
public Calculator() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
xpanel = new JPanel();
xpanel.setLayout(new GridLayout(3,2));
xpanel.add(new JLabel("x:"));
xfield = new JTextField("0", 5);
xpanel.add(xfield);
xpanel.add(new JLabel("y:"));
yfield = new JTextField("0", 5);
xpanel.add(yfield);
xpanel.add(new JLabel("x*y="));
result = new JLabel("0");
xpanel.add(result);
frame.add(xpanel, BorderLayout.NORTH);
subtractButton = new JButton("Subtract");
frame.add(subtractButton, BorderLayout.SOUTH);
subtractButton.addActionListener(this);
divideButton = new JButton("Division");
frame.add(divideButton, BorderLayout.SOUTH);
divideButton.addActionListener(this);
frame.pack();
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent event) {
int x = 0;
int y = 0;
String xText = xfield.getText();
String yText = yfield.getText();
try {
x = Integer.parseInt(xText);
}
catch (NumberFormatException e) {
x = 0;
}
try {
y = Integer.parseInt(yText);
}
catch (NumberFormatException e) {
y = 0;
}
result.setText(Integer.toString(x-y));
}
}
You need to add both buttons in a JPanel before adding that JPanel in the SOUTH of your frame.
So instead of
subtractButton = new JButton("Subtract");
frame.add(subtractButton, BorderLayout.SOUTH);
subtractButton.addActionListener(this);
divideButton = new JButton("Division");
frame.add(divideButton, BorderLayout.SOUTH);
divideButton.addActionListener(this);
You can do this
JPanel southPanel = new JPanel();
subtractButton = new JButton("Subtract");
southPanel.add(subtractButton);
subtractButton.addActionListener(this);
divideButton = new JButton("Division");
southPanel.add(divideButton);
divideButton.addActionListener(this);
frame.add(southPanel , BorderLayout.SOUTH);
Use Eclipse and WindowBuilder for your Swing interfaces and add as many buttons as you like or move them around with your mouse. Its much easier especially if you are new to this and you'll learn a lot from the generated code.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I created the Food tab using code below
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
addIt(tabbedPane, "Foods");
addIt1(tabbedPane, "Drinks");
addIt1(tabbedPane, "Desserts");
tabbedPane.setBounds(10, 11, 400, 450);
frame.getContentPane().add(tabbedPane);
Here the addIt methods
static void addIt(JTabbedPane tabbedPane, String text) throws IOException {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
JTextField textField = new JTextField(2);
BufferedImage myPicture = ImageIO.read(new File("C:\\Users\\tony\\Desktop\\MedSalad.png"));
Image scaled = myPicture.getScaledInstance(80,95,Image.SCALE_SMOOTH);
JLabel picLabel = new JLabel("Salad",new ImageIcon(scaled),JLabel.CENTER);
picLabel.setHorizontalTextPosition(JLabel.CENTER);
picLabel.setVerticalTextPosition(JLabel.BOTTOM);
JTextField textField1 = new JTextField(2);
BufferedImage myPicture1 = ImageIO.read(new File("C:\\Users\\tony\\Desktop\\JapanesePanNoodles.png"));
Image scaled1 = myPicture1.getScaledInstance(80,95,Image.SCALE_SMOOTH);
JLabel picLabel1 = new JLabel("Japanese Noodles",new ImageIcon(scaled1),JLabel.CENTER);
picLabel1.setHorizontalTextPosition(JLabel.CENTER);
picLabel1.setVerticalTextPosition(JLabel.BOTTOM);
JTextField textField2 = new JTextField(2);
BufferedImage myPicture2 = ImageIO.read(new File("C:\\Users\\tony\\Desktop\\Spaghetti.png"));
Image scaled2 = myPicture2.getScaledInstance(80,95,Image.SCALE_SMOOTH);
JLabel picLabel2 = new JLabel("Spaghetti",new ImageIcon(scaled2),JLabel.CENTER);
picLabel2.setHorizontalTextPosition(JLabel.CENTER);
picLabel2.setVerticalTextPosition(JLabel.BOTTOM);
JTextField textField3 = new JTextField(2);
BufferedImage myPicture3 = ImageIO.read(new File("C:\\Users\\tony\\Desktop\\PadThai.png"));
Image scaled3 = myPicture3.getScaledInstance(80,95,Image.SCALE_SMOOTH);
JLabel picLabel3 = new JLabel("Spaghetti Meat Balls",new ImageIcon(scaled3),JLabel.CENTER);
picLabel3.setHorizontalTextPosition(JLabel.CENTER);
picLabel3.setVerticalTextPosition(JLabel.BOTTOM);
JTextField textField4 = new JTextField(2);
BufferedImage myPicture4 = ImageIO.read(new File("C:\\Users\\tony\\Desktop\\RamenNoodles.png"));
Image scaled4 = myPicture4.getScaledInstance(80,95,Image.SCALE_SMOOTH);
JLabel picLabel4 = new JLabel("Noodles",new ImageIcon(scaled4),JLabel.CENTER);
picLabel4.setHorizontalTextPosition(JLabel.CENTER);
picLabel4.setVerticalTextPosition(JLabel.BOTTOM);
JTextField textField5 = new JTextField(2);
BufferedImage myPicture5 = ImageIO.read(new File("C:\\Users\\tony\\Desktop\\SpaghettiAndMeatBalls.png"));
Image scaled5 = myPicture5.getScaledInstance(80,95,Image.SCALE_SMOOTH);
JLabel picLabel5 = new JLabel("Kids Spaghetti",new ImageIcon(scaled5),JLabel.CENTER);
picLabel5.setHorizontalTextPosition(JLabel.CENTER);
picLabel5.setVerticalTextPosition(JLabel.BOTTOM);
JTextField textField6 = new JTextField(2);
BufferedImage myPicture6 = ImageIO.read(new File("C:\\Users\\tony\\Desktop\\chickenRice.jpg"));
Image scaled6 = myPicture6.getScaledInstance(80,95,Image.SCALE_SMOOTH);
JLabel picLabel6 = new JLabel("Chicken Rice",new ImageIcon(scaled6),JLabel.CENTER);
picLabel6.setHorizontalTextPosition(JLabel.CENTER);
picLabel6.setVerticalTextPosition(JLabel.BOTTOM);
JTextField textField7 = new JTextField(2);
BufferedImage myPicture7 = ImageIO.read(new File("C:\\Users\\tony\\Desktop\\thaiFood.jpeg"));
Image scaled7 = myPicture7.getScaledInstance(80,95,Image.SCALE_SMOOTH);
JLabel picLabel7 = new JLabel("Thai Food",new ImageIcon(scaled7),JLabel.CENTER);
picLabel7.setHorizontalTextPosition(JLabel.CENTER);
picLabel7.setVerticalTextPosition(JLabel.BOTTOM);
JTextField textField8 = new JTextField(2);
BufferedImage myPicture8 = ImageIO.read(new File("C:\\Users\\tony\\Desktop\\vietnamFood.jpg"));
Image scaled8 = myPicture8.getScaledInstance(80,95,Image.SCALE_SMOOTH);
JLabel picLabel8 = new JLabel("Vietnam Food",new ImageIcon(scaled8),JLabel.CENTER);
picLabel8.setHorizontalTextPosition(JLabel.CENTER);
picLabel8.setVerticalTextPosition(JLabel.BOTTOM);
panel.add(picLabel);
panel.add(textField);
panel.add(picLabel1);
panel.add(textField1);
panel.add(picLabel2);
panel.add(textField2);
panel.add(picLabel3);
panel.add(textField3);
panel.add(picLabel4);
panel.add(textField4);
panel.add(picLabel5);
panel.add(textField5);
panel.add(picLabel6);
panel.add(textField6);
panel.add(picLabel7);
panel.add(textField7);
panel.add(picLabel8);
panel.add(textField8);
tabbedPane.addTab(text, panel);
}
And here the screen shot of Food Tab
MainClass
public class FoodOrdering {
private JFrame frame;
private JTextField textField;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
FoodOrdering window = new FoodOrdering();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public FoodOrdering() throws IOException {
initialize();
}
private void initialize() throws IOException {
frame = new JFrame();
frame.setBounds(100, 100, 700, 550);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
frame.setLocationRelativeTo(null);
JLabel lblFoodOrdered = new JLabel("Food Ordered");
lblFoodOrdered.setBounds(529, 11, 81, 14);
frame.getContentPane().add(lblFoodOrdered);
TextArea textArea = new TextArea();
textArea.setBounds(462, 31, 199, 275);
frame.getContentPane().add(textArea);
JLabel lblTotal = new JLabel("Total : ");
lblTotal.setBounds(519, 315, 46, 14);
frame.getContentPane().add(lblTotal);
textField = new JTextField();
textField.setBounds(575, 312, 86, 20);
frame.getContentPane().add(textField);
textField.setColumns(10);
JButton btnOrder = new JButton("Order");
btnOrder.setBounds(521, 352, 89, 23);
frame.getContentPane().add(btnOrder);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
addIt(tabbedPane, "Foods");
addIt1(tabbedPane, "Drinks");
addIt1(tabbedPane, "Desserts");
tabbedPane.setBounds(23, 11, 400, 450);
frame.getContentPane().add(tabbedPane);
}
How can I align the picture, JTextField in the same line ?
I don't have images to test, there's no valid MCVE in the question, however from what I see in it you could try (in order of preference)
Using GridBagLayout instead of FlowLayout that you're currently using, this will help placing your images in a grid and align them in it.
Using GridLayout which will make your images and JTextFields the same size and placing them in a grid of the same size, each component.
Resizing your images to be all the same size, before getting their getScaledInstance(...)
BTW, this tabbedPane.setBounds(10, 11, 400, 450); suggests that in some point of your code, you're using null layout, you should know that null layout is evil and thus it's use is frowned upon. If you're not using null layout anywhere (we can't know because we don't have that code in the question), then, that line is needed.
Also, you could improve your code by wrapping all the same functionality like this:
JTextField textField1 = new JTextField(2);
BufferedImage myPicture1 = ImageIO.read(new File("C:\\Users\\tony\\Desktop\\JapanesePanNoodles.png"));
Image scaled1 = myPicture1.getScaledInstance(80,95,Image.SCALE_SMOOTH);
JLabel picLabel1 = new JLabel("Japanese Noodles",new ImageIcon(scaled1),JLabel.CENTER);
picLabel1.setHorizontalTextPosition(JLabel.CENTER);
picLabel1.setVerticalTextPosition(JLabel.BOTTOM);
inside a method where it receives the image name and label text, as the rest of the code is identical to the other ones, and then you could call that method inside a loop, that could really improve the code written by you, legibility and simplicity.
From my above recommendations, you can use GridBagLayout using the GridBagConstraints to place your elements where you want, avoiding the use of null layout:
frame.getContentPane().setLayout(null); //COMPLETELY WRONG!!!!!!
In this example, I used two images of different sizes, so, you can see, that even like that, your fields will stay the same size.
The following code is a MCVE, the one you posted isn't (and I'm surprised of you having almost 3K rep not knowing how to make a proper MCVE)
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class FoodMenu {
private JFrame frame;
private JPanel pane;
private GridBagConstraints gbc;
private JLabel[] foodLabel;
private JTextField[] qtyField;
private static final int ELEMENTS = 9;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new FoodMenu().createAndShowGui());
}
private void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
pane = new JPanel();
pane.setLayout(new GridBagLayout());
gbc = new GridBagConstraints();
foodLabel = new JLabel[ELEMENTS];
qtyField = new JTextField[ELEMENTS];
ImageIcon icon = null, icon2 = null;
try {
URL url = new URL("https://image.flaticon.com/icons/png/128/148/148836.png");
URL url2 = new URL("https://i.stack.imgur.com/IucNt.png");
BufferedImage img = ImageIO.read(url);
icon = new ImageIcon(img);
BufferedImage img2 = ImageIO.read(url2);
icon2 = new ImageIcon(img2);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
for (int i = 0; i < ELEMENTS; i++) {
foodLabel[i] = new JLabel(i % 2 == 0 ? icon : icon2);
qtyField[i] = new JTextField(3);
}
gbc.gridx = 0;
for (int i = 0; i < ELEMENTS; i++) {
if (i % 3 == 0) {
gbc.gridy++;
gbc.gridx = 0;
}
pane.add(foodLabel[i], gbc);
gbc.gridx++;
pane.add(qtyField[i], gbc);
gbc.gridx++;
}
frame.add(pane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
But how can I display the food label below the food image ?
Change the for loop as below
gbc.gridx = 0;
for (int i = 0; i < ELEMENTS; i++) {
if (i % 3 == 0) {
gbc.gridy += 2;
gbc.gridx = 0;
}
pane.add(foodLabel[i], gbc);
gbc.gridy++;
pane.add(qtyField[i], gbc);
gbc.gridx++;
gbc.gridy--;
}
I'm trying to implement a JPanel that displays more or less information depending on the available size.
Basically, the idea is have a default content like this:
That can shrinks to this when the space is reduced:
My code is like this:
import net.miginfocom.swing.MigLayout;
import javax.swing.*;
class PanelDemo extends JPanel {
private final JLabel title = new JLabel();
private final JLabel counter1 = new JLabel("00");
private final JLabel counter1Label = new JLabel();
private final JLabel counter2 = new JLabel("00");
private final JLabel counter2Label = new JLabel();
/**
* Instantiates a new obs app cadre message bloc panel.
*/
public PanelDemo() {
this.setOpaque(false);
initGUI();
}
private final void initGUI() {
// 1°)
final MigLayout migLayout = new MigLayout(
"fillx, hidemode 2, debug",
"[growprio 0][]" //define 4 columns
);
setLayout(migLayout);
// 2°)
//
add(title, "spanx");
add(counter1, "newline");
add(counter1Label);
add(counter2);
add(counter2Label);
}
public static void main(String[] args) {
final JFrame jFrame = new JFrame("test 4");
jFrame.getContentPane().setLayout(new MigLayout("fillx, debug"));
final PanelDemo item1 = new PanelDemo();
item1.title.setText("Element 1");
item1.counter1Label.setText("First lbl");
item1.counter2Label.setText("Second lbl");
jFrame.getContentPane().add(item1, "growx, gpx 110");
final PanelDemo item2 = new PanelDemo();
item2.title.setText("Element 2");
item2.counter1Label.setText("First lbl");
item2.counter2Label.setText("Second lbl");
jFrame.getContentPane().add(item2, "growx, gpx 100");
jFrame.pack();
jFrame.setVisible(true);
} }
I tried to add a ComponentListener and override componentResized() to find when I could show/hide my secondary labels but I was not successful.
Does anybody know how to implement such a behaviour that goes well with MigLayout grow priorities?
Update1: I was thinking... what if I set the minimum width to counter1+label1, and the maximum size to counter2+label2 and then listen to resize operations and change the preferred size to either its minimum or its maximum. Would that mecanism work?
How about this:
public static JPanel panel(String name) {
JPanel panel = new JPanel(new MigLayout("insets 0, wrap 4, fillx, debug", "[][][shrink 200][shrink 200, grow 200]"));
panel.add(new JLabel(name), "spanx 4");
panel.add(new JLabel("00"));
panel.add(new JLabel("First lbl"));
panel.add(new JLabel("01"));
panel.add(new JLabel("Second lbl"));
return panel;
}
public static void main(String[] args) {
JPanel panel = new JPanel(new MigLayout("insets 10, gap 10, fillx, debug"));
panel.add(panel("Element 1"), "w (50% - 15)!");
panel.add(panel("Element 2"), "w (50% - 15)!");
JFrame frame = new JFrame();
frame.setContentPane(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
I had trouble getting the two main columns to resize equally; I had to do it by setting a width on the components rather than the columns. I'm not sure why that is.
I implemented an autohide mechanism with a LayoutCallback switching the visibility of the component depending on the width of the panel.
Here is an example:
MigLayout layout = new MigLayout("fill");
JPanel panel = new JPanel(layout);
JLabel label1 = new JLabel("Label 1");
label1.putClientProperty("autohide.width", 300);
JLabel label2 = new JLabel("Label 2");
label2.putClientProperty("autohide.width", 200);
panel.add(label1, "grow");
panel.add(label2, "grow");
layout.addLayoutCallback(new LayoutCallback() {
#Override
public void correctBounds(ComponentWrapper wrapper) {
JComponent component = (JComponent) wrapper.getComponent();
Number width = (Number) component.getClientProperty("autohide.width");
if (width != null) {
if (component.isVisible() && wrapper.getParent().getWidth() < width.intValue()) {
component.setVisible(false);
} else if (!component.isVisible() && wrapper.getParent().getWidth() > width.intValue()) {
component.setVisible(true);
}
}
}
});
Here the label1 is hidden when the width of the panel shrinks below 300 pixels, and label2 disappears when the width is less than 200 pixels.