I made a small program with two buttons. I label
the buttons one exiting the program and the second importing files.
I actually let them both to exit the program when ever someone pressed on it
the problem is the buttons taking all the window, why?
I tried GridBagConstraints to resize the buttons some how but no luck anyway here's the full class without imports..
public class Window2 extends JFrame{
private static final long serialVersionUID = 1L;
public Window2(){
super ("ALANAZ imagtor");
setSize(600,400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel pnl1 = new JPanel(new GridLayout());
JPanel pnl2 = new JPanel();
//button
JButton butn1 = new JButton("EXIT");
JButton butn2 =new JButton("IMPORT");
butn1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JOptionPane.showMessageDialog(null, "exiting ... bye...");
System.exit(0);
}
});
butn2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
JOptionPane.showMessageDialog(null, "can't import now exiting");
System.exit(0);
}
});
GridBagConstraints gb1 = new GridBagConstraints();
gb1.insets = new Insets(15,15,15,15);
//Jlabel
JLabel lbl1 = new JLabel("exit or import an image");
pnl1.add(butn1);
pnl1.add(butn2);
pnl2.add(lbl1);
add(pnl2, BorderLayout.SOUTH);
add(pnl1, BorderLayout.CENTER);
}}
You are misusing your layout managers. Your pnl1 JPanel uses GridLayout (without any row or column constants?!), and if you only add one component to it, it will take up the entire JPanel. You seem to have GridBagConstraints in your code, but no GridBagLayout, which is confusing to me.
The solution is to read up on and understand how to use layout managers. Please have a look at the tutorial link: Laying Out Components Within a Container.
Key is to keep remembering that you can nest JPanels within JPanels. For example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
public class Window2 extends JFrame {
private static final long serialVersionUID = 1L;
private static final int PREF_W = 600;
private static final int PREF_H = 400;
public Window2() {
super("ALANAZ imagtor");
setDefaultCloseOperation(EXIT_ON_CLOSE);
int gap = 3;
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, gap, 0));
buttonPanel.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
JPanel pnl2 = new JPanel();
JButton butn1 = new JButton("EXIT");
JButton butn2 = new JButton("IMPORT");
butn1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "exiting ... bye...");
System.exit(0);
}
});
butn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JOptionPane.showMessageDialog(null, "can't import now exiting");
System.exit(0);
}
});
JLabel lbl1 = new JLabel("exit or import an image");
buttonPanel.add(butn1);
buttonPanel.add(butn2);
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.add(buttonPanel, BorderLayout.SOUTH);
pnl2.add(lbl1);
add(pnl2, BorderLayout.SOUTH);
add(centerPanel, BorderLayout.CENTER);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public static void main(String[] args) {
Window2 win2 = new Window2();
win2.pack();
win2.setLocationRelativeTo(null);
win2.setVisible(true);
}
}
If you initialize your panel with a BorderLayout instead, and add your buttons using EAST, NORTH, WEST, SOUTH, you will have a quick fix - however I do also recommend reading up on layout managers
JPanel pnl1 = new JPanel(new BorderLayout());
pnl1.add(new JButton(), BorderLayout.SOUTH);
Related
I have been trying to pass the info of my JTextField that is in a JDialog into my JFrame. Both the JDialog and JFrame are in separate classes. I have tried to store the JTextField into a JLable using the .setText and .getText and then passing the JLable into the JFrame but with no luck.
I know there are many similar questions but I have tried many different approaches but still no luck. I am relatively new to Java and do not know all the in's and out's. Any help is very appreciated!
My code for the JFrame:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JPanel;
public class StockApp extends JFrame implements PropertyChangeListener {
private JPanel main = new JPanel();
private JPanel north = new JPanel();
private JPanel center = new JPanel();
private JPanel south = new JPanel();
private JButton buyStock = new JButton("Buy Stock");
private JButton sellStock = new JButton("Sell Stock");
public TestTest variables = new TestTest();
private JLabel stockNameNorth = new JLabel("Stock Name");
private JLabel stockPriceNorth = new JLabel("Stock Price");
String stockName = variables.getStockName();
String stockPrice = variables.getStockPrice();
public StockApp() {
setTitle("StockApp");
getContentPane().setBackground(Color.white);
setSize(400,400);
setLocation(500,200);
setVisible(true);
main.setLayout(new BorderLayout());
north.setLayout(new FlowLayout());
center.setLayout(new FlowLayout());
south.setLayout(new FlowLayout());
stockNameNorth.setText(stockName);
stockPriceNorth.setText(stockPrice);
add(main);
north.add(stockNameNorth);
north.add(stockPriceNorth);
south.add(buyStock);
south.add(sellStock);
main.add(north, BorderLayout.NORTH);
main.add(center, BorderLayout.CENTER);
main.add(south, BorderLayout.SOUTH);
}
}
And Dialog:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TestTest extends JDialog implements ActionListener {
private JPanel main = new JPanel();
private JPanel north = new JPanel();
private JPanel center = new JPanel();
private JPanel south = new JPanel();
private JLabel stockNameLabel = new JLabel("Stock name: ");
private JLabel stockPriceLabel = new JLabel("Stock price(£): ");
private JTextField stockNameIn = new JTextField(5);
private JTextField stockPriceIn = new JTextField(5);
private JButton buttonOK = new JButton("OK");
public JLabel stockPrice = new JLabel();
public JLabel stockName = new JLabel();
public TestTest() {
getContentPane().setBackground(Color.white);
setSize(400,400);
setLocation(500,200);
setModal(false);
setVisible(true);
getRootPane().setDefaultButton(buttonOK);
main.setLayout(new BorderLayout());
north.setLayout(new FlowLayout());
center.setLayout(new FlowLayout());
south.setLayout(new FlowLayout());
add(main);
north.add(stockNameLabel);
north.add(stockNameIn);
center.add(stockPriceLabel);
center.add(stockPriceIn);
south.add(buttonOK);
main.add(north, BorderLayout.NORTH);
main.add(center, BorderLayout.CENTER);
main.add(south, BorderLayout.SOUTH);
buttonOK.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == buttonOK){
stockName.setText(stockNameIn.getText());
stockPrice.setText(stockPriceIn.getText());
dispose();
new StockApp();
}
}
public String getStockName() {
return stockNameIn.getText();
}
public String getStockPrice() {
return stockPriceIn.getText();
}
}
I am trying to pass the stockName and stockPrice variables from the JDialog into the JFrame. I then want the name and price to display at the top of the JFrame.
For demonstration, what the problem is, we need less Fields and Buttons.
So far, no component of StockApp needs to be accessed from different methods, so there is no need to make them visible outside of the ctor.
More explanations in the code.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
public class StockApp extends JFrame {
public StockApp() {
// move those unreferenced panels here, so we don't have to reason about them:
JPanel main = new JPanel();
JPanel north = new JPanel();
JPanel center = new JPanel();
JPanel south = new JPanel();
// add price later, when name works
JButton buyStock = new JButton("Buy Stock");
JLabel stockNameNorth = new JLabel("Stock Name");
// critical change: Make the label, which you like to update,
// accessible by whom it should be updated:
TestTest variables = new TestTest (stockNameNorth);
setTitle ("StockApp");
getContentPane().setBackground(Color.white);
setSize (600,400);
setLocation (500,200);
setVisible (true);
// make the close-frame action terminate the program:
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
main.setLayout (new BorderLayout());
north.setLayout (new FlowLayout());
center.setLayout (new FlowLayout());
south.setLayout (new FlowLayout());
add (main);
north.add (stockNameNorth);
south.add (buyStock);
main.add (north, BorderLayout.NORTH);
main.add (center, BorderLayout.CENTER);
main.add (south, BorderLayout.SOUTH);
}
// Main method to start the damn thing
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new StockApp ();
}
});
}
}
// no need to make this class public in a short test:
class TestTest extends JDialog implements ActionListener {
// this are elements, visible outside the construction phase,
// we need to have access to from more than one method.
// Make this important distinction visible to the reader:
JLabel name;
JTextField stockNameIn = new JTextField (5);
JButton buttonOK = new JButton ("OK");
// add the JLabel to update to the ctor, so that it can't be forgotten
// to be set
public TestTest (JLabel pname) {
// we copy the reference to the label, to have access to it in
// the actionPerformed method.
name = pname;
JPanel main = new JPanel();
JPanel north = new JPanel();
JPanel center = new JPanel();
JPanel south = new JPanel();
JLabel stockNameLabel = new JLabel ("Stock name: ");
getContentPane().setBackground(Color.white);
// different size/location than frame, so that they don't hide
// each other completly
setSize (400,600);
setLocation (700,300);
setModal (false);
setVisible (true);
getRootPane().setDefaultButton(buttonOK);
main.setLayout (new BorderLayout());
north.setLayout (new FlowLayout());
center.setLayout (new FlowLayout());
south.setLayout (new FlowLayout());
add (main);
north.add (stockNameLabel);
north.add (stockNameIn);
south.add (buttonOK);
main.add (north, BorderLayout.NORTH);
main.add (center, BorderLayout.CENTER);
main.add (south, BorderLayout.SOUTH);
buttonOK.addActionListener(this);
}
// here we need access to the button - was it the OK-Button, clicked?
// and the textfield stockNameIn, to read the text
// and the name field from the frame, to set the text
public void actionPerformed(ActionEvent e) {
if (e.getSource () == buttonOK) {
name.setText (stockNameIn.getText());
dispose();
}
}
}
How to set Jbuttons to a specific place when you have a background in JLabel : code below
i can't get the jlabel to stay at the top and the buttons to stay south(bottom) ??
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonsClass extends JFrame
implements ActionListener {
JButton b1 = new JButton("button1");
JButton b2 = new JButton("button2");
JButton b3 = new JButton("button3");
JButton b4 = new JButton("button4");
JLabel label = new JLabel("buttons:");
public static void main(String[] args) {
new ButtonsClass();
}
public Jukebox() {
setLayout(new BorderLayout());
setContentPane(new JLabel(new ImageIcon("image.png")));
setLayout(new FlowLayout());
setSize(500,150);
setTitle("Backgroundwithbuttons");
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
JPanel top = new JPanel();
top.add(label);
add("North", top);
JPanel bottom = new JPanel();
bottom.add(b1);
bottom.add(b2);
bottom.add(b3);
bottom.add(b4);
add("South", bottom);
setVisible(true);
}
}
" i can't get the jlabel to stay at the top and the buttons to stay south(bottom)"
That's because you set the layout the BorderLayout, then immediately set it to FlowLayout. With FlowLayout, your BorderLayout positioning will do nothing.
setLayout(new BorderLayout());
setContentPane(new JLabel(new ImageIcon("image.png")));
setLayout(new FlowLayout());
Just get rid of the setLayout(new FlowLayout());
Also your constructor is wrong
public Jukebox() {
-Should be-
public ButtonClass() {
Also you need to set the layout of the JLabel that you set as the content pane. Yout constructor should look like this
public ButtonClass() {
JLabel background = new JLabel(new ImageIcon("image.png"));
background.setLayout(new BorderLayout());
setContentPane(background);
setTitle("Background with buttons");
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
JPanel top = new JPanel();
top.add(label);
add(top, BorderLayout.NORTH);
JPanel bottom = new JPanel();
bottom.add(b1);
bottom.add(b2);
bottom.add(b3);
bottom.add(b4);
add(bottom, BorderLayout.SOUTH);
//pack();
setVisible(true);
}
Also, add("North", top); is a deprecated method. Instead use add(top, BorderLayout.NORTH) and same for add(bottom, BorderLayout.SOUTH)
Also, Swing apps should be run on the Event Dispatch Thread. You can do so by wrapping the code in your main with a SwingUtilities.invokeLater...
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ButtonClass();
}
});
}
Also, you should set the panel's opaque property to false, if you want the image to show behind them.
top.setOpaque(false);
bottom.setOpaque(false);
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonClass extends JFrame
implements ActionListener {
JButton b1 = new JButton("button1");
JButton b2 = new JButton("button2");
JButton b3 = new JButton("button3");
JButton b4 = new JButton("button4");
JLabel label = new JLabel("buttons:");
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ButtonClass();
}
});
}
public ButtonClass() {
label.setForeground(Color.WHITE);
JLabel background = new JLabel(new ImageIcon(getClass().getResource("/resources/space.png")));
background.setLayout(new BorderLayout());
setContentPane(background);
setTitle("Background with buttons");
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
JPanel top = new JPanel();
top.setOpaque(false);
top.add(label);
add(top, BorderLayout.NORTH);
JPanel bottom = new JPanel();
bottom.setOpaque(false);
bottom.add(b1);
bottom.add(b2);
bottom.add(b3);
bottom.add(b4);
add(bottom, BorderLayout.SOUTH);
setSize(400, 300);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {}
}
Try using:
add(bottom, BorderLayout.SOUTH);
instead of:
add("South", bottom);
BorderLayout tutorial
Whenever I press "clear" in my Java GUI, it never works, please help me finish this. If i replace "textPanel" with another button, it works, otherwise with "textpanel" it doesn't.
Here is a lightweight version of my code demonstrating the problem:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MainFrame extends JFrame {
private TextPanel textPanel;
private FormPanel formpanel;
public MainFrame(){
super("My Frame");
createLayout();
createFrame();
}
public void createFrame(){
setSize(600, 600);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public void createLayout(){
BorderLayout myLayout = new BorderLayout();
setLayout(myLayout);
textPanel = new TextPanel();
formpanel = new FormPanel();
// adding components
add(textPanel, BorderLayout.CENTER);
add(formpanel, BorderLayout.WEST);
}
public static void main(String[] args){
new MainFrame();
}
public static class FormPanel extends JPanel {
private JButton clear;
private TextPanel textPanel;
public FormPanel(){
clear = new JButton("Clear Cart!");
textPanel=new TextPanel();
add(clear);
clear.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent aev){
System.out.println("Test");
textPanel.setText("");
}
});
createGrid();
}
/* this methods simply creates the layout */
void createGrid(){
//creating layout
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.gridy++;
gc.weightx = .1;
gc.weighty = .1;
gc.gridx = 2;
gc.gridy=5;
gc.anchor = GridBagConstraints.LINE_START;
gc.insets = new Insets(0,0,0,0);
add(clear, gc);
}
}
public static class TextPanel extends JPanel {
private JTextArea textArea;
TextPanel (){
textArea = new JTextArea();
setLayout(new BorderLayout());
JScrollPane p = new JScrollPane(textArea);
add(p, BorderLayout.CENTER);
}
public void appendSomeText(String t){
textArea.append(t);
}
public void setText(String s){
textArea.setText(s);
}
}
}
You have two instances of TextPanel, one in MainFrame and the other one in FormPanel. TextPanel that is defined in FormPanel is actually not added to the panel, so textPanel.setText(""); has no effect on it as it is not visible.
When the text appended with Add To Cart! button it actually goes through a method in MainFrame - formEventOccurred() that executes textPanel.appendSomeText(). This is the other instance of TextPanel that is part of MainFrame and that is actually visible.
Looks like you need to move the duplicated logic from the main frame to the panels. Usually you should not extend JFrame as you are not adding any new functionality.
I am a beginner to java. In second cardpanel the username and password alignment is not coming properly. Is there any way to fix it? I would also like to know what is the disadvantage of using multiple frames.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class CardLayoutTest extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel cardPanel, jp1, jp2, buttonPanel;
private JLabel jl1, jl2;
private JTextField jt1;
private JPasswordField jt2;
private JButton btn1, btn2;
private CardLayout cardLayout = new CardLayout();
public CardLayoutTest() {
setTitle("Login");
setSize(400, 300);
cardPanel = new JPanel();
buttonPanel = new JPanel();
cardPanel.setLayout(cardLayout);
jp1 = new JPanel();
jp2 = new JPanel();
jt1=new JTextField();
jt2=new JPasswordField();
jl1 = new JLabel("Username");
jl2 = new JLabel("Password");
//jp1.add(jl1);
jp2.add(jl1);
jp2.add(jt2);
jp2.add(jl2);
jp2.add(jt2);
cardPanel.add(jp1, "1");
cardPanel.add(jp2, "2");
btn2 = new JButton("Show Card 2");
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardLayout.show(cardPanel, "2");
}
});
buttonPanel.add(btn2);
add(cardPanel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
CardLayoutTest frame = new CardLayoutTest();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
In second cardpanel the username and password alignment is not coming properly.
By default a JPanel uses a FlowLayout so the components are displayed on a single line.
Is there any way to fix it?
Use an appropriate layout manager (or combination of layout managers) to get the desired alignment.
Read the section from the Swing tutorial on Layout Managers for more information and examples.
I want to know how to add components dynamically to a JDialog. I know there is a similar question on SO here, but as you can see, I have his solution as a part of my code.
So the idea is that on click of the button, I need to add a component on the dialog. The sample code is below:
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public static void main(String args[]) {
Test test = new Test();
test.createDialog();
}
public void createDialog() {
DynamicDialog dialog = new DynamicDialog(this);
dialog.setSize(300, 300);
dialog.setVisible(true);
}
}
class DynamicDialog extends JDialog {
/**
*
*/
private static final long serialVersionUID = 1L;
public DynamicDialog(final JFrame owner) {
super(owner, "Dialog Title", Dialog.DEFAULT_MODALITY_TYPE);
final JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.add(Box.createRigidArea(new Dimension(3, 10)));
panel.add(createLabel("Click on add"));
panel.add(Box.createRigidArea(new Dimension(23, 10)));
panel.add(createLabel("To add another line of text"));
panel.add(Box.createHorizontalGlue());
mainPanel.add(panel);
mainPanel.add(Box.createRigidArea(new Dimension(3, 10)));
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
buttonPanel.add(Box.createHorizontalGlue());
JButton button = new JButton();
button.setText("Add another line");
buttonPanel.add(button);
mainPanel.add(buttonPanel);
mainPanel.add(Box.createRigidArea(new Dimension(3, 10)));
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
Container contentPane = owner.getContentPane();
JPanel _panel = new JPanel();
_panel.setLayout(new BoxLayout(_panel, BoxLayout.X_AXIS));
_panel.add(Box.createHorizontalGlue());
_panel.add(createLabel("Added!"));
contentPane.add(_panel);
contentPane.validate();
contentPane.repaint();
owner.pack();
}
});
pack();
setLocationRelativeTo(owner);
this.add(mainPanel);
}
JLabel createLabel(String name) {
JLabel label = new JLabel(name);
return label;
}
}
If you add it to the main panel it will work, you were adding it to the content pane of the frame which it seems it does not show up anywhere.
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
JPanel _panel = new JPanel();
_panel.setLayout(new BoxLayout(_panel, BoxLayout.X_AXIS));
_panel.add(Box.createHorizontalGlue());
_panel.add(createLabel("Added!"));
mainPanel.add(_panel);
mainPanel.validate();
mainPanel.repaint();
owner.pack();
}
})