This question already has answers here:
JFrame background image
(4 answers)
Closed 6 years ago.
I searched for a way to add an Image as an Bakground for my JFrame.
I found some Questions for that and tried several solutions but my Image won't show up and I don't know what's wrong (I'm a noob btw xd)
I DID see the other Questions but they DID NOT help me, I tried really hard but can't find my fault! So please (Human who marked my post as duplicate).
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class prognose extends Frame {
// Anfang Attribute
private JTextField spendenbetrag = new JTextField();
private JTextField streamzeit = new JTextField();
private JLabel sBetragL = new JLabel();
private JLabel sZeitL = new JLabel();
private JButton prognosebutton = new JButton();
private ImageIcon prognosebuttonIcon = new ImageIcon("C:\\Users\\user\\Documents\\Programmieren\\Workspace\\images\\Button.png");
private JTextField ergebnis = new JTextField();
// Ende Attribute
public prognose() {
// Frame-Initialisierung
super();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) { dispose(); }
});
int frameWidth = 455;
int frameHeight = 580;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setTitle("Loot für die Welt");
setResizable(false);
Panel cp = new Panel(null);
add(cp);
// Anfang Komponenten
spendenbetrag.setText("");
cp.add(spendenbetrag);
streamzeit.setText("");
cp.add(streamzeit);
sBetragL.setText("Aktueller Spendenbetrag");
cp.add(sBetragL);
streamzeit.setBounds(152, 184, 145, 25);
spendenbetrag.setBounds(152, 112, 145, 25);
sBetragL.setBounds(152, 80, 145, 25);
sZeitL.setBounds(152, 152, 155, 25);
sZeitL.setText("Aktuelle Streamzeit");
cp.add(sZeitL);
prognosebutton.setBounds(184, 224, 80, 280);
prognosebutton.setText("");
prognosebutton.setMargin(new Insets(2, 2, 2, 2));
prognosebutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
prognosebutton_ActionPerformed(evt);
}
});
prognosebutton.setIcon(prognosebuttonIcon);
prognosebutton.setBorderPainted(false);
prognosebutton.setBackground(Color.WHITE);
prognosebutton.setBorder(BorderFactory.createEtchedBorder(0, Color.DARK_GRAY, new Color(0xC0C0C0)));
prognosebutton.setIconTextGap(0);
cp.setBackground(Color.WHITE);
setUndecorated(false);
cp.add(prognosebutton);
ergebnis.setBounds(152, 512, 145, 25);
ergebnis.setText("");
ergebnis.setEditable(false);
cp.add(ergebnis);
// Ende Komponenten
setVisible(true);
setLayout(new BorderLayout());
setSize(455,580);
setVisible(true);
JLabel background=new JLabel(new ImageIcon("C:\\Users\\user\\Documents\\Programmieren\\Workspace\\images\\Background.png"));
add(background);
background.setLayout(new FlowLayout());
} // end of public prognose
// Anfang Methoden
public static void main(String[] args) {
new prognose();
} // end of main
public void prognosebutton_ActionPerformed(ActionEvent evt) {
// TODO hier Quelltext einfügen
String a;
String b;
a = spendenbetrag.getText();
b = streamzeit.getText();
double d;
double e = Double.parseDouble(a);
double f = Double.parseDouble(b);
d = e*(60/f)*48;
d = ((double)((int)(d*100)))/100;
String g = String.valueOf(d);
ergebnis.setText(g);
} // end of prognosebutton_ActionPerformed
// Ende Methoden
} // end of class prognose
Extend JFrame instead of Frame, use the setComponentPane to set the backround, Move the declaration of the background label to the top of the code. Add all the components to that label.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class prognose extends JFrame {
// Anfang Attribute
private JTextField spendenbetrag = new JTextField();
private JTextField streamzeit = new JTextField();
private JLabel sBetragL = new JLabel();
private JLabel sZeitL = new JLabel();
private JButton prognosebutton = new JButton();
private ImageIcon prognosebuttonIcon = new ImageIcon("C:\\test\\rak.png");
private JTextField ergebnis = new JTextField();
// Ende Attribute
public prognose() {
// Frame-Initialisierung
super();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) { dispose(); }
});
int frameWidth = 455;
int frameHeight = 580;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setTitle("Loot für die Welt");
setResizable(false);
JLabel background=new JLabel(new ImageIcon("C:\\test\\rak.png"));
setContentPane(background);
background.setLayout(new FlowLayout());
Panel cp = new Panel(null);
background.add(cp);
// Anfang Komponenten
spendenbetrag.setText("");
background.add(spendenbetrag);
streamzeit.setText("");
background.add(streamzeit);
sBetragL.setText("Aktueller Spendenbetrag");
background.add(sBetragL);
streamzeit.setBounds(152, 184, 145, 25);
spendenbetrag.setBounds(152, 112, 145, 25);
sBetragL.setBounds(152, 80, 145, 25);
sZeitL.setBounds(152, 152, 155, 25);
sZeitL.setText("Aktuelle Streamzeit");
background.add(sZeitL);
prognosebutton.setBounds(184, 224, 80, 280);
prognosebutton.setText("");
prognosebutton.setMargin(new Insets(2, 2, 2, 2));
prognosebutton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
prognosebutton_ActionPerformed(evt);
}
});
prognosebutton.setIcon(prognosebuttonIcon);
prognosebutton.setBorderPainted(false);
prognosebutton.setBackground(Color.WHITE);
prognosebutton.setBorder(BorderFactory.createEtchedBorder(0, Color.DARK_GRAY, new Color(0xC0C0C0)));
prognosebutton.setIconTextGap(0);
background.setBackground(Color.WHITE);
setUndecorated(false);
background.add(prognosebutton);
ergebnis.setBounds(152, 512, 145, 25);
ergebnis.setText("");
ergebnis.setEditable(false);
background.add(ergebnis);
// Ende Komponenten
setVisible(true);
setLayout(new BorderLayout());
setSize(455,580);
setVisible(true);
} // end of public prognose
// Anfang Methoden
public static void main(String[] args) {
new prognose();
} // end of main
public void prognosebutton_ActionPerformed(ActionEvent evt) {
// TODO hier Quelltext einfügen
String a;
String b;
a = spendenbetrag.getText();
b = streamzeit.getText();
double d;
double e = Double.parseDouble(a);
double f = Double.parseDouble(b);
d = e*(60/f)*48;
d = ((double)((int)(d*100)))/100;
String g = String.valueOf(d);
ergebnis.setText(g);
} // end of prognosebutton_ActionPerformed
// Ende Methoden
} // end of class prognose
Related
I have a weird problem and I have no idea what causes this.
I have a dialog class which simply shows an error/warning message to the screen. Interestingly, when I set the window center, the components does not appear (unless I re-size it).
However, when I change the screen location, components appear on the JPanel just fine.
I basically change this line to int x = (dim.width - w) / 3;and it works. But it doesn't when the width divided by 2. So, the dialog works anywhere but center. Please, let me know what I am missing here.
I appreciate any help!
Thank you!
Here's the code:
An MCVE:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class UKDialog extends JDialog {
private JButton button1;
private JLabel message;
public UKDialog(String message, String buttonText) {
this.button1 = new JButton(buttonText);
this.message = new JLabel(message);
setWarning();
}
public void setWarning() {
this.setModal(true);
this.setAlwaysOnTop(true);
if (this.message.getText().length() <= 30) {
this.setMaximumSize(new Dimension(650, 300));
this.setMinimumSize(new Dimension(650, 300));
this.setPreferredSize(new Dimension(650, 300));
} else if (this.message.getText().length() > 30) {
this.setMaximumSize(new Dimension(870, 300));
this.setMinimumSize(new Dimension(870, 300));
this.setPreferredSize(new Dimension(870, 300));
}
this.setLayout(new BorderLayout());
JPanel messagePanel = new JPanel();
messagePanel.setBorder(BorderFactory.createEtchedBorder());
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
buttonPanel.setBorder(BorderFactory.createEtchedBorder());
buttonPanel.setPreferredSize(new Dimension(600, 100));
this.message.setFont(new Font("Calibri", Font.BOLD, 40));
this.button1.setPreferredSize(new Dimension(230, 80));
this.button1.setFont(new Font("Calibri", Font.BOLD, 45));
this.button1.setBackground(new java.awt.Color(139, 71, 137));
this.button1.setForeground(java.awt.Color.white);
this.button1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
okActionPerformed(evt);
}
});
messagePanel.add(this.message, BorderLayout.CENTER);
buttonPanel.add(this.button1);
this.add(messagePanel, BorderLayout.CENTER);
this.add(buttonPanel, BorderLayout.SOUTH);
// calculate the new location of the window
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int w = this.getSize().width;
int h = this.getSize().height;
int x = (dim.width - w) / 2;
int y = (dim.height - h) / 5;
this.setLocation(x, y);
this.setVisible(true);
}
protected void okActionPerformed(ActionEvent evt) {
UKDialog.this.dispose();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final JFrame frame = new JFrame("Main GUI");
JButton button = new JButton(new AbstractAction("Push Me") {
#Override
public void actionPerformed(ActionEvent e) {
String message = "Message is Long Enough???";
String buttonText = "Button";
UKDialog ukDialog = new UKDialog(message, buttonText);
}
});
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(500, 400));
panel.add(button);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
This is my class calls the warning class with the main method.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ScrollPaneLayout;
import javax.swing.WindowConstants;
public class PAndDeliveryNotification extends JDialog {
private JButton button1;
private JLabel messageTitle;
private JTextField text;
private boolean reply;
private String typedText;
private ArrayList<String[]> remainingInvoices;
private String stopNum = null;
private String currentStopNum, lastStopNum;
public PAndDeliveryNotification(ArrayList<String[]> rInvoices, String buttonText1) {
this.button1 = new JButton(buttonText1);
this.remainingInvoices = rInvoices;
}
public void setDelivStopNo() throws IOException {
BufferedImage image = null;
try {
image = ImageIO.read(new File("images/uk.png"));
} catch (IOException e) {
}
this.setIconImage(image);
//frame properties
this.setModal(true);
this.setAlwaysOnTop(true);
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
this.setLayout(new BorderLayout());
//frame size
this.setPreferredSize(new Dimension(900, 600));
this.setMaximumSize(new Dimension(900, 600));
this.setMinimumSize(new Dimension(900, 600));
JPanel upperPanel = new JPanel(new WrapLayout());
upperPanel.setBorder(BorderFactory.createEtchedBorder());
for (int i = 0; i < this.remainingInvoices.size(); i++) {
String[] invoice;
invoice = (String[]) this.remainingInvoices.get(i);
if (i == 0) {
this.currentStopNum = invoice[0];
}
if (i == this.remainingInvoices.size() - 1) {
this.lastStopNum = invoice[0];
}
StopItem item = new StopItem(invoice);
item.setPreferredSize(new Dimension(770, 120));
upperPanel.add(item);
}
upperPanel.repaint();
upperPanel.revalidate();
JScrollPane pane = new JScrollPane(upperPanel);
pane.setPreferredSize(new Dimension(770, 600));
pane.getVerticalScrollBar().setPreferredSize(new Dimension(50, 0));
pane.setLayout(new ScrollPaneLayout());
this.add(pane, BorderLayout.CENTER);
JPanel lowerPanel = new JPanel(new BorderLayout());
lowerPanel.setBorder(BorderFactory.createEtchedBorder());
lowerPanel.setPreferredSize(new Dimension(600, 100));
JPanel messagePanel = new JPanel(new FlowLayout());
messagePanel.setPreferredSize(new Dimension(600, 80));
JPanel buttonPanel = new JPanel();
buttonPanel.setPreferredSize(new Dimension(240, 80));
this.messageTitle = new JLabel("Enter Delivery Stop Number:");
this.messageTitle.setFont(new Font("Calibri", Font.BOLD, 40));
this.messageTitle.setPreferredSize(new Dimension(480, 80));
this.text = new JTextField(3);
this.text.setPreferredSize(new Dimension(100, 80));
this.text.setFont(new Font("Calibri", Font.BOLD, 40));
this.text.setHorizontalAlignment(JTextField.CENTER);
this.text.requestFocus();
Runtime.getRuntime().exec("cmd /c tabtip.exe");
this.button1.setPreferredSize(new Dimension(230, 80));
this.button1.setFont(new Font("Calibri", Font.BOLD, 45));
this.button1.setBackground(new java.awt.Color(139, 71, 137));
this.button1.setForeground(java.awt.Color.white);
this.button1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
saveStopNumActionPerformed(evt);
}
});
messagePanel.add(this.messageTitle);
messagePanel.add(this.text);
buttonPanel.add(this.button1);
lowerPanel.add(messagePanel, BorderLayout.WEST);
lowerPanel.add(buttonPanel, BorderLayout.EAST);
this.add(pane, BorderLayout.CENTER);
this.add(lowerPanel, BorderLayout.SOUTH);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
// calculate the new location of the window
int w = this.getSize().width;
int h = this.getSize().height;
int x = (dim.width - w) / 2;
int y = 0;
this.setLocation(x, y);
this.setVisible(true);
}
private void saveStopNumActionPerformed(ActionEvent evt) {
this.stopNum = this.text.getText();
try {
if (stopNum == null) {
new UKDialog("Fields cannot be empty!", "OK");
return;
} else if (Integer.parseInt(stopNum) < Integer.parseInt(this.currentStopNum)) {
new UKDialog("Delivery cannot be before pick up!", "OK");
return;
} else if (Integer.parseInt(stopNum) > Integer.parseInt(this.lastStopNum) + 1) {
new UKDialog("Enter stop number between " + this.currentStopNum + 1 + " and "
+ this.lastStopNum, "OK");
return;
}
} catch (NumberFormatException e) {
new UKDialog("Please enter numeric values!", "OK");
return;
}
System.out.println(this.stopNum);
this.setVisible(false);
this.dispose();
}
public String getStopNum() {
return this.stopNum;
}
private class StopItem extends JPanel {
private JPanel numPanel = new JPanel();
private JLabel itemNumber = new JLabel();
private JPanel leftPanel = new JPanel();
private JLabel invNoLbl = new JLabel();
private JLabel consigneeLbl = new JLabel();
private JLabel locationLbl = new JLabel();
private final String pUStopNo;
private final String invoiceNo;
private final String consignee;
private final String location;
public StopItem(String[] invoice) {
this.pUStopNo = invoice[0];
this.invoiceNo = invoice[1];
this.consignee = invoice[2];
this.location = invoice[3];
//Left and numberpanels
this.numPanel.setLayout(new BorderLayout());
this.numPanel.setPreferredSize(new Dimension(80, 80));
this.leftPanel.setLayout(new BorderLayout());
this.leftPanel.setPreferredSize(new Dimension(200, 90));
//number panel
this.itemNumber.setFont(new java.awt.Font("Lucida Grande", Font.BOLD, 45));
this.itemNumber.setText(String.valueOf(" " + pUStopNo));
//this.numPanel.setBorder(BorderFactory.createEtchedBorder());
this.numPanel.add(this.itemNumber);
//Main panel
this.setLayout(new BorderLayout());
this.setBorder(BorderFactory.createLineBorder(Color.black, 2));
this.invNoLbl.setText("Invoice #: " + this.invoiceNo);
this.invNoLbl.setFont(new java.awt.Font("Calibri", Font.PLAIN, 35));
this.consigneeLbl.setText("Consignee: " + this.consignee);
this.consigneeLbl.setFont(new java.awt.Font("Calibri", Font.PLAIN, 35));
this.locationLbl.setText("Location: " + this.location);
this.locationLbl.setFont(new java.awt.Font("Calibri", Font.PLAIN, 35));
this.leftPanel.add(this.invNoLbl, BorderLayout.NORTH);
this.leftPanel.add(this.consigneeLbl, BorderLayout.CENTER);
this.leftPanel.add(this.locationLbl, BorderLayout.SOUTH);
// add all the components to the frame
this.add(this.numPanel, BorderLayout.WEST);
this.add(this.leftPanel, BorderLayout.CENTER);
}
}
public static void main(String[] args) throws IOException {
String[] array1 = {"6", "444555", "Ali Murtaza Sumer", "Carson, Ca 90746"};
String[] array2 = {"7", "444666", "Hasan Huseyin Karabiber", "Los Angeles, Ca 90746"};
String[] array3 = {"8", "444777", "Mustafa Tinaztepe", "Macomb, IL 61455"};
String[] array4 = {"9", "444888", "Berkay Surmeli", "Chicago, IL 60625"};
String[] array5 = {"6", "444555", "Ali Murtaza Sumer", "Carson, Ca 90746"};
String[] array6 = {"7", "444666", "Hasan Huseyin Karabiber", "Los Angeles, Ca 90746"};
String[] array7 = {"8", "444777", "Mustafa Tinaztepe", "Macomb, IL 61455"};
String[] array8 = {"9", "444888", "Berkay Surmeli", "Chicago, IL 60625"};
ArrayList<String[]> aL = new ArrayList<>();
aL.add(array1);
aL.add(array2);
aL.add(array3);
aL.add(array4);
PAndDeliveryNotification question = new PAndDeliveryNotification(aL, "SAVE");
question.setDelivStopNo();
}
}
Edit:
You using two JDialog exending Classes. Both of them has setAlwaysOnTop(true) and setModal(true) therefore both are competing for the view. Maybe you should use a JFrame and JDialog
I have an issue where when I include the JPanel in my JFrame, it covers the entire screen. My code reads
import java.awt.*;
import javax.swing.*;
public class TestFrameExample extends JPanel {
static String TheQuestion;
static String QN1 = "Question 1: ";
static String Q1 = "What is Lead's chemical symbol?";
static String brk = "___________________";
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(new Color(135, 206, 250));
g.setFont(new Font("Tahoma", Font.BOLD, 48));
g.setColor(Color.WHITE);
g.drawString(QN1, 80, 100);
g.setFont(new Font("Tahoma", Font.BOLD, 48));
g.setColor(Color.WHITE);
g.drawString(brk, 60, 130);
g.setFont(new Font("Tahoma", Font.PLAIN, 36));
g.setColor(Color.WHITE);
g.drawString(Q1, 80, 200);
}
public static void main(String[] args) {
TestFrameExample graphics = new TestFrameExample();
JFrame ThisFrame = new JFrame();
TheQuestion = QN1;
JTextField txt = new JTextField(10);
JPanel Panel = new JPanel();
ThisFrame.setTitle("Question 1");
ThisFrame.setSize(720, 480);
ThisFrame.setLocationRelativeTo(null);
ThisFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ThisFrame.setVisible(true);
ThisFrame.add(graphics);
Panel.setBackground(new Color(135, 206, 250));
Panel.setSize(null);
Panel.setLocation(null);
Panel.add(txt);
ThisFrame.add(Panel);
}
}
However, when I change
Panel.setLocation(null)
to
Panel.setLocation(80, 250)
It covers the entire screen.
Could someone please help me put it in the right spot on the screen?
UPDATE
I made the modifications as I said in my comment, with the code reading
import java.awt.*;
import javax.swing.*;
public class TestFrameExample extends JPanel {
static String TheQuestion;
static String QN1 = "Question 1: ";
static String Q1 = "What is Lead's chemical symbol?";
static String brk = "___________________";
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(new Color(135, 206, 250));
g.setFont(new Font("Tahoma", Font.BOLD, 48));
g.setColor(Color.WHITE);
g.drawString(QN1, 80, 100);
g.setFont(new Font("Tahoma", Font.BOLD, 48));
g.setColor(Color.WHITE);
g.drawString(brk, 60, 130);
g.setFont(new Font("Tahoma", Font.PLAIN, 36));
g.setColor(Color.WHITE);
g.drawString(Q1, 80, 200);
}
public static void main(String[] args) {
TestFrameExample graphics = new TestFrameExample();
JFrame ThisFrame = new JFrame();
TheQuestion = QN1;
JTextField txt = new JTextField(20);
JPanel panel = new JPanel();
ThisFrame.setTitle("Question 1");
ThisFrame.setSize(720, 480);
ThisFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ThisFrame.add(graphics);
panel.setBackground(new Color(135, 206, 250));
panel.add(txt);
ThisFrame.add(panel);
ThisFrame.add(panel, BorderLayout.PAGE_END);
ThisFrame.setLocationRelativeTo(null);
ThisFrame.setVisible(true);
}
}
It places the input txt at the bottom of the screen, but the rest of the screen remains grey.
But I simply don't understand the second set of code that you posted; it's far beyond my skill set (I've only been learning Java for the last 6 weeks). All I'm looking for at this stage is make the panel not blank out the rest of the screen.
Is this possible just by modifying the current set of code, or would I have to completely rewrite the code?
A JFrame's contentPane uses BorderLayout by default, and you can use that to your advantage:
Add your TestFrameExample object BorderLayout.CENTER to your JFrame
Add your other JPanel, or perhaps just a JTextField to the JFrame in the BorderLayout.PAGE_END position. This will add the component to the bottom of the GUI.
Don't call setLocation(...) on your components as that's inviting use of null layouts, a layout that leads to rigid GUI's that are hard to debug and upgrade.
For more details, read up on the BorderLayout in the tutorials.
e.g.,
public static void main(String[] args) {
TestFrameExample graphics = new TestFrameExample();
JFrame thisFrame = new JFrame();
TheQuestion = QN1;
JTextField txt = new JTextField(10);
JPanel panel = new JPanel();
thisFrame.setTitle("Question 1");
thisFrame.setSize(720, 480); // better to not do this, but to pack instead
// thisFrame.setLocationRelativeTo(null);
thisFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// thisFrame.setVisible(true); // *** not yet ***
thisFrame.add(graphics, BorderLayout.CENTER);
panel.setBackground(new Color(135, 206, 250));
// panel.setSize(null); // *** don't do this ***
// panel.setLocation(null); // *** don't do this ***
panel.add(txt);
thisFrame.add(panel, BorderLayout.PAGE_END);
thisFrame.setLocationRelativeTo(null);
thisFrame.setVisible(true); // *** HERE ***
}
Note that myself, I'd avoid direct painting if possible and instead would use components and layout managers. This should make it easier to display different kinds of questions. For example, run the following program and by pressing the <enter> key repeatedly, scroll the questions to see just what I mean:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class TestQuestion2 extends JPanel {
private static final Color BACKGROUND = new Color(135, 206, 250);
private static final Color LABEL_FOREGROUND = Color.white;
private static final int EB_GAP = 60;
private static final int PREF_W = 720;
private static final int PREF_H = 480;
private static final Font TITLE_FONT = new Font("Tahoma", Font.BOLD, 48);
private static final Font Q_FONT = TITLE_FONT.deriveFont(Font.PLAIN, 36f);
private JLabel questionTitleLabel = new JLabel();
private JTextArea questionArea = new JTextArea(4, 10);
private JTextField answerField = new JTextField(20);
private Question question;
private List<Question> questionList;
private int questionListIndex = 0;
public TestQuestion2(List<Question> questionList) {
this.questionList = questionList;
questionTitleLabel.setFont(TITLE_FONT);
questionTitleLabel.setForeground(LABEL_FOREGROUND);
JSeparator separator = new JSeparator();
separator.setForeground(LABEL_FOREGROUND);
questionArea.setFont(Q_FONT);
questionArea.setForeground(LABEL_FOREGROUND);
questionArea.setWrapStyleWord(true);
questionArea.setLineWrap(true);
questionArea.setBorder(null);
questionArea.setOpaque(false);
questionArea.setFocusable(false);
JScrollPane scrollPane = new JScrollPane(questionArea);
scrollPane.setBorder(null);
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
JPanel answerPanel = new JPanel();
answerPanel.add(answerField);
answerPanel.setOpaque(false);
setBackground(BACKGROUND);
setBorder(BorderFactory.createEmptyBorder(EB_GAP, EB_GAP, EB_GAP, EB_GAP));
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(questionTitleLabel);
add(Box.createHorizontalStrut(10));
add(separator);
add(Box.createHorizontalStrut(5));
add(scrollPane);
add(Box.createHorizontalGlue());
add(answerPanel);
setQuestion(questionList.get(questionListIndex));
answerField.addActionListener(new AnswerListener());
}
public void setQuestion(Question question) {
this.question = question;
questionTitleLabel.setText("Question " + question.getNumber() + ":");
questionArea.setText(question.getQuestion());
}
#Override
public Dimension getPreferredSize() {
Dimension superSz = super.getPreferredSize();
if (isPreferredSizeSet()) {
return superSz;
}
int prefW = Math.max(superSz.width, PREF_W);
int prefH = Math.max(superSz.height, PREF_H);
return new Dimension(prefW, prefH);
}
private class AnswerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
questionListIndex++;
questionListIndex %= questionList.size();
setQuestion(questionList.get(questionListIndex));
}
}
private static void createAndShowGui() {
List<Question> questionList = new ArrayList<>();
questionList.add(new Question(1, "What is Lead's chemical symbol?"));
questionList.add(new Question(2, "Who is buried in Grant's tomb?"));
questionList.add(new Question(3, "What ..... is your quest?"));
questionList.add(new Question(4, "What ..... is your favorite color?"));
questionList.add(new Question(5, "What is the capital of Assyria?"));
questionList.add(new Question(6, "What is the airspeed velocity of the unladen laden swallow?"));
questionList.add(new Question(7, "This will be a very long question, one that shows the display "
+ "of multiple lines, and a JTextArea that looks like a JLabel. "
+ "What do you think of it?"));
TestQuestion2 testQuestion2Panel = new TestQuestion2(questionList);
JFrame frame = new JFrame("Question");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(testQuestion2Panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class Question {
private int number;
private String question;
private List<String> possibleAnswers;
public Question(int number, String question) {
this.number = number;
this.question = question;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
}
I am trying to get a text input from a JTextField and displaying it on a JTextField when a button is clicked. Can anyone help please?
I know I am supposed to use getText and setText but not quite sure how I can implement this when the button is clicked. Please have a look at the code below.
Thanks.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class CyberPet extends JFrame
implements ActionListener {
private JButton makePetButton,hungryButton, randomButton;
private JPanel panel;
private JLabel label, petName, flyLabel;
private JTextArea responseArea;
private JTextField textField;
int x =10;
int y=10;
int xMax = 700;
int yMax = 500;
public static void main (String[] args) {
CyberPet frame = new CyberPet();
frame.setSize(700, 500);
frame.createGUI();
frame.show();
frame.getContentPane().setBackground(Color.blue);
}
private void createGUI() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container window = getContentPane();
window.setLayout(new FlowLayout() );
JPanel buttonGUI = new JPanel();
panel = new JPanel();
panel.setPreferredSize(new Dimension(500, 300));
panel.setLocation(500, 300);
panel.setBackground(Color.white);
panel.setLayout(null);
window.add(panel);
buttonGUI = new JPanel();
buttonGUI.setPreferredSize(new Dimension(400, 100));
buttonGUI.setLocation(200, 100);
buttonGUI.setBackground(Color.white);
window.add(buttonGUI);
label = new JLabel();
label.setBackground(Color.white);
Image img = new ImageIcon (this.getClass().getResource("/frog.gif")).getImage();
label.setIcon(new ImageIcon(img));
label.setLocation(400, 0);
label.setSize(80, 80);
panel.add(label);
flyLabel = new JLabel();
flyLabel.setBackground(Color.black);
Image img1 = new ImageIcon (this.getClass().getResource("/fly.gif")).getImage();
flyLabel.setIcon(new ImageIcon(img1));
flyLabel.setLocation(10, 10);
flyLabel.setSize(50, 50);
panel.add(flyLabel);
petName = new JLabel("Enter Pet Name!");
buttonGUI.add(petName);
textField = new JTextField("");
textField.setPreferredSize(new Dimension(100, 30));
textField.setLocation(200, 60);
textField.addActionListener(this);
buttonGUI.add(textField);
makePetButton = new JButton("Make Pet");
makePetButton.setLocation(160, 60);
makePetButton.addActionListener(this);
buttonGUI.add(makePetButton);
hungryButton = new JButton("Hungry!");
hungryButton.setLocation(280, 60);
hungryButton.setSize(100, 30);
hungryButton.addActionListener(this);
buttonGUI.add(hungryButton);
responseArea = new JTextArea("Pet Status");
buttonGUI.add(responseArea);
}
// ***** nb line of 4 spaces after insert
public void actionPerformed(ActionEvent event) {
//Move down
if (event.getSource() == makePetButton)
{
}
//Move Up
if (event.getSource() == hungryButton)
{
if (y > 10){
y=y-20;
label.setLocation(x, y);
}
}
//Makes the Pet
if (event.getSource() == makePetButton)
{
if (x > 10){
x=x-20;
label.setLocation(x, y);
}
}
//Move Right
if (event.getSource() == textField)
{
if (x < 280){
x=x+20;
label.setLocation(x, y);
}
}
//Move random
if(event.getSource() == randomButton)
{
Random rnd = new Random();
int xMax = panel.getWidth()-label.getWidth();
int yMax = panel.getHeight()-label.getHeight();
x = rnd.nextInt(xMax+10);
y = rnd.nextInt(yMax+10);
label.setLocation(x,y);
}
}
}
You have the eventHandler, so just call responseArea.setText(textField.getText()) when handling the click on the appropriate button.
I have a JTextField in a JFrame. The caret blinks between a normal looking caret and a half drawn caret.
The caret only shows at the top and bottom. I have tried using custom carets but they all only show part of the graphic. The bug is the same for the password field too. I don't know if it's relevant but I'm on a mac and I don't own a windows machine to test if the bug occurs on windows as well.
Here is an MCVE of my window (as short as I could make it):
public class Login1 extends JFrame implements Serializable {
private static final long serialVersionUID = 1L;
private JPanel pnl_mainPanel;
private JButton btn_login_main, btn_newAccount, btn_seeAccounts, btn_login_login, btn_cancel_login, btn_next, btn_cancel_new;
private JTextField tf_username_login, tf_username_new;
private JPasswordField pf_password, pf_password_new, pf_password_confirm;
private JLabel lbl_username_login, lbl_password_login, lbl_username_new, lbl_password_new, lbl_password_confirm;
private static final String TITLE = "Login";
private final int WINDOW_WIDTH = 400;
private final int WINDOW_HEIGHT = 300;
private final Dimension WINDOW_DIM = new Dimension(WINDOW_WIDTH, WINDOW_HEIGHT);
public Login1() {
super(TITLE);
setSize(WINDOW_DIM);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
buildPanel();
add(pnl_mainPanel);
setVisible(true);
setResizable(false);
}
private void buildPanel() {
pnl_mainPanel = new JPanel();
btn_login_main = new JButton("Login");
btn_newAccount = new JButton("New Account");
btn_seeAccounts = new JButton("ℹ");
// login page
btn_login_login = new JButton("Login");
btn_cancel_login = new JButton("Cancel");
tf_username_login = new JTextField();
pf_password = new JPasswordField();
lbl_username_login = new JLabel("Username:");
lbl_password_login = new JLabel("Password:");
// new account page
btn_next = new JButton("Next");
btn_cancel_new = new JButton("Cancel");
tf_username_new = new JTextField();
pf_password_new = new JPasswordField();
pf_password_confirm = new JPasswordField();
lbl_username_new = new JLabel("Username:");
lbl_password_new = new JLabel("Password:");
lbl_password_confirm = new JLabel("<html>Confirm<br>Password:</html>");
pnl_mainPanel.setLayout(null);
pnl_mainPanel.add(btn_login_main);
pnl_mainPanel.add(btn_newAccount);
pnl_mainPanel.add(btn_seeAccounts);
btn_login_login.setSize(75, 30);
btn_login_login.setLocation(new Point(310, 175));
btn_cancel_login.setSize(75, 30);
btn_cancel_login.setLocation(new Point(310, 215));
tf_username_login.setSize(200, 25);
tf_username_login.setLocation(new Point(100, 178));
pf_password.setSize(200, 25);
pf_password.setLocation(new Point(100, 218));
lbl_username_login.setSize(100, 25);
lbl_username_login.setLocation(new Point(15, 178));
lbl_password_login.setSize(100, 25);
lbl_password_login.setLocation(new Point(15, 218));
btn_next.setSize(75, 30);
btn_next.setLocation(new Point(310, 160));
btn_cancel_new.setSize(75, 30);
btn_cancel_new.setLocation(new Point(310, 200));
tf_username_new.setSize(200, 25);
tf_username_new.setLocation(new Point(100, 163));
pf_password_new.setSize(200, 25);
pf_password_new.setLocation(new Point(100, 203));
pf_password_confirm.setSize(200, 25);
pf_password_confirm.setLocation(new Point(100, 243));
lbl_username_new.setSize(100, 25);
lbl_username_new.setLocation(new Point(15, 163));
lbl_password_new.setSize(100, 25);
lbl_password_new.setLocation(new Point(15, 203));
lbl_password_confirm.setSize(100, 30);
lbl_password_confirm.setLocation(new Point(15, 238));
btn_login_main.setSize(163, 100);
btn_login_main.setLocation(new Point(25, 150));
btn_newAccount.setSize(162, 100);
btn_newAccount.setLocation(new Point(213, 150));
btn_seeAccounts.setSize(20, 20);
btn_seeAccounts.setLocation(new Point(375, 255));
btn_login_main.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pnl_mainPanel.remove(btn_login_main);
pnl_mainPanel.remove(btn_newAccount);
pnl_mainPanel.remove(btn_next);
pnl_mainPanel.remove(btn_cancel_new);
pnl_mainPanel.remove(tf_username_new);
pnl_mainPanel.remove(pf_password_new);
pnl_mainPanel.remove(pf_password_confirm);
pnl_mainPanel.remove(lbl_username_new);
pnl_mainPanel.remove(lbl_password_new);
pnl_mainPanel.remove(lbl_password_confirm);
pnl_mainPanel.add(btn_login_login);
pnl_mainPanel.add(btn_cancel_login);
pnl_mainPanel.add(tf_username_login);
pnl_mainPanel.add(pf_password);
pnl_mainPanel.add(lbl_username_login);
pnl_mainPanel.add(lbl_password_login);
repaint();
tf_username_login.requestFocus();
}
});
btn_cancel_login.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pnl_mainPanel.remove(btn_login_login);
pnl_mainPanel.remove(tf_username_login);
pnl_mainPanel.remove(pf_password);
pnl_mainPanel.remove(btn_cancel_login);
pnl_mainPanel.remove(lbl_username_login);
pnl_mainPanel.remove(lbl_password_login);
pnl_mainPanel.add(btn_login_main);
pnl_mainPanel.add(btn_newAccount);
repaint();
}
});
btn_newAccount.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pnl_mainPanel.remove(btn_login_main);
pnl_mainPanel.remove(btn_newAccount);
pnl_mainPanel.add(btn_next);
pnl_mainPanel.add(btn_cancel_new);
pnl_mainPanel.add(tf_username_new);
pnl_mainPanel.add(pf_password_new);
pnl_mainPanel.add(pf_password_confirm);
pnl_mainPanel.add(lbl_username_new);
pnl_mainPanel.add(lbl_password_new);
pnl_mainPanel.add(lbl_password_confirm);
repaint();
tf_username_new.requestFocus();
}
});
btn_cancel_new.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pnl_mainPanel.remove(btn_next);
pnl_mainPanel.remove(btn_cancel_new);
pnl_mainPanel.remove(tf_username_new);
pnl_mainPanel.remove(pf_password_new);
pnl_mainPanel.remove(pf_password_confirm);
pnl_mainPanel.remove(lbl_username_new);
pnl_mainPanel.remove(lbl_password_new);
pnl_mainPanel.remove(lbl_password_confirm);
pnl_mainPanel.add(btn_login_main);
pnl_mainPanel.add(btn_newAccount);
repaint();
}
});
}
public static void main(String[] args){
Login1 l = new Login1();
}
}
Thanks in advance!
I can confirm that this happens on my Mac, and does not happen on my Linux.
It can be easily solved by changing the height of the field to at least 28.
tf_username_login.setSize(200, 28);
My guess is that Mac OS X cannot create a field whose height is less than 28 pixels (though this may be a question of font choice etc., I haven't tested it that far). For some reason, it draws the full caret at full height (28 pixels), but erases it at the user indicated size (25) which causes the phenomenon you have noticed.
I have a panel with two buttons. I'm trying to insert an image inside the panel and I want to draw lines inside the image after clicking on a button. I have used the below code but this doesn't seem to work.
public class Try_Panel extends JFrame {
// start attributes
private JPanel jPanel1 = new JPanel(null, true);
private JButton jButton1 = new JButton();
private JButton jButton2 = new JButton();
// end attributes
public Try_Panel(String title) {
// Frame-Init
super(title);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
int frameWidth = 300;
int frameHeight = 300;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setResizable(false);
Container cp = getContentPane();
cp.setLayout(null);
// start components
jPanel1.setBounds(48, 24, 209, 145);
jPanel1.setOpaque(false);
cp.add(jPanel1);
jButton1.setBounds(88, 208, 75, 25);
jButton1.setText("jButton1");
jButton1.setMargin(new Insets(2, 2, 2, 2));
jButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton1_ActionPerformed(evt);
}
});
cp.add(jButton1);
jButton2.setBounds(184, 208, 75, 25);
jButton2.setText("jButton2");
jButton2.setMargin(new Insets(2, 2, 2, 2));
jButton2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton2_ActionPerformed(evt);
}
});
cp.add(jButton2);
// end components
setVisible(true);
} // end of public Try_Panel
// start methods
public void jButton1_ActionPerformed(ActionEvent evt) {
BufferedImage image=new BufferedImage(jPanel1.getWidth(), jPanel1.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
JLabel l=new JLabel(new ImageIcon(image));
Graphics graphics = image.getGraphics();
Graphics2D g = (Graphics2D) graphics;
g.fillRect(0, 0, image.getWidth(), image.getHeight());
g.setColor(Color.BLUE);
g.drawLine(0, 0, 300, 400);
jPanel1.add(l);
} // end of jButton1_ActionPerformed
public void jButton2_ActionPerformed(ActionEvent evt) {
// TODO add your code here
} // end of jButton2_ActionPerformed
// end methods
public static void main(String[] args) {
new Try_Panel("Try_Panel");
} // end of main
} // end of class Try_Panel
The biggest problem is the same code worked in my other class.
Try wrapping the image inside the ImageIcon AFTER you have updated it. Also, you should also call Graphics#dispose when you are finished rendering to the graphics context.
public void jButton1_ActionPerformed(ActionEvent evt) {
BufferedImage image=new BufferedImage(jPanel1.getWidth(), jPanel1.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = image.createGraphics();
g.fillRect(0, 0, image.getWidth(), image.getHeight());
g.setColor(Color.BLUE);
g.drawLine(0, 0, 300, 400);
g.dispose();
JLabel l=new JLabel(new ImageIcon(image));
jPanel1.add(l);
}
You should also rely on the layout managers rather the trying to do it yourself, it will simply make your life easier.
Personally, I think it would easier to paint directly to a custom component, like JPanel. Check out Performing Custom Painting for more details
UPDATED with example
Basically, I changed your example to
Use layout managers
Load the UI within the context of the EDT
revalidate the jPanel1
public class BadLabel extends JFrame {
// start attributes
private JPanel jPanel1 = new JPanel(new BorderLayout(), true);
private JButton jButton1 = new JButton();
private JButton jButton2 = new JButton();
// end attributes
public BadLabel(String title) {
// Frame-Init
super(title);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
int frameWidth = 300;
int frameHeight = 300;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
// setResizable(false);
Container cp = getContentPane();
// cp.setLayout(null);
// start components
// jPanel1.setBounds(48, 24, 209, 145);
jPanel1.setOpaque(true);
jPanel1.setBackground(Color.RED);
cp.add(jPanel1);
JPanel buttons = new JPanel();
// jButton1.setBounds(88, 208, 75, 25);
jButton1.setText("jButton1");
jButton1.setMargin(new Insets(2, 2, 2, 2));
jButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton1_ActionPerformed(evt);
}
});
buttons.add(jButton1);
// jButton2.setBounds(184, 208, 75, 25);
jButton2.setText("jButton2");
jButton2.setMargin(new Insets(2, 2, 2, 2));
jButton2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton2_ActionPerformed(evt);
}
});
buttons.add(jButton2);
// end components
cp.add(buttons, BorderLayout.SOUTH);
setVisible(true);
} // end of public BadLabel
// start methods
public void jButton1_ActionPerformed(ActionEvent evt) {
BufferedImage image = new BufferedImage(jPanel1.getWidth(), jPanel1.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = image.createGraphics();
g.fillRect(0, 0, image.getWidth(), image.getHeight());
g.setColor(Color.BLUE);
g.drawLine(0, 0, 300, 400);
g.dispose();
JLabel l = new JLabel(new ImageIcon(image));
l.setBorder(new LineBorder(Color.BLUE));
jPanel1.add(l);
jPanel1.revalidate();
} // end of jButton1_ActionPerformed
public void jButton2_ActionPerformed(ActionEvent evt) {
// TODO add your code here
} // end of jButton2_ActionPerformed
// end methods
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception exp) {
}
new BadLabel("BadLabel");
}
});
} // end of main
} // end of class BadLabel}
Something like this:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.border.EmptyBorder;
public class Try_Panel {
// start attributes
private JButton jButton1 = new JButton("jButton1");
private JButton jButton2 = new JButton("jButton2");
private JLabel imageView;
BufferedImage image;
int x = 300;
int y = 50;
// end attributes
public Component getGui() {
JPanel gui = new JPanel(new BorderLayout(5, 5));
gui.setBorder(new EmptyBorder(3, 3, 3, 3));
image = new BufferedImage(300, 100, BufferedImage.TYPE_INT_RGB);
imageView = new JLabel(new ImageIcon(image));
gui.add(imageView, BorderLayout.CENTER);
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 15));
gui.add(buttons, BorderLayout.PAGE_END);
jButton1.setMargin(new Insets(2, 2, 2, 2));
jButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton1_ActionPerformed(evt);
}
});
buttons.add(jButton1);
jButton2.setMargin(new Insets(2, 2, 2, 2));
jButton2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
jButton2_ActionPerformed(evt);
}
});
buttons.add(jButton2);
// end components
return gui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
public void run() {
// Frame-Init
JFrame f = new JFrame("Try Panel");
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
Container cp = f.getContentPane();
cp.setLayout(new BorderLayout(3, 3));
Try_Panel tp = new Try_Panel();
cp.add(tp.getGui());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
} // end of public Try_Panel
// start methods
public void jButton1_ActionPerformed(ActionEvent evt) {
Graphics graphics = image.getGraphics();
Graphics2D g = (Graphics2D) graphics;
g.setColor(Color.RED);
g.drawLine(0, 0, x, y);
x -= 4;
y += 2;
g.dispose();
imageView.repaint();
} // end of jButton1_ActionPerformed
public void jButton2_ActionPerformed(ActionEvent evt) {
// TODO add your code here
} // end of jButton2_ActionPerformed
} // end of class Try_Panel