Enter text, push button, why does the pie chart does not display?
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.TitledBorder;
public class PieChart extends JFrame {
private JTextField jtfParticipation = new JTextField();
private JTextField jtfProjects = new JTextField();
private JTextField jtfQuizzes = new JTextField();
private JTextField jtfFinalExam = new JTextField();
private JButton jbtCreatePieChart = new JButton("Create Pie Chart");
public PieChart() {
// Text panel
JPanel panel1 = new JPanel(new GridLayout(8, 0));
panel1.setBorder(new TitledBorder("Input percentages:"));
// A font to change from the default Plain font to Arial font
Font arialFont = new Font("Arial", Font.PLAIN, 12);
JLabel jlblParticipation = new JLabel("Participation %");
JLabel jlblProjects = new JLabel("Projects %");
JLabel jlblQuizzes = new JLabel("Quizzes %");
JLabel jlblFinalExam = new JLabel("Final Exam %");
// The labels use the new font
jlblParticipation.setFont(arialFont);
jlblProjects.setFont(arialFont);
jlblQuizzes.setFont(arialFont);
jlblFinalExam.setFont(arialFont);
// Adds the objects to the panel
panel1.add(jlblParticipation);
panel1.add(jtfParticipation);
panel1.add(jlblProjects);
panel1.add(jtfProjects);
panel1.add(jlblQuizzes);
panel1.add(jtfQuizzes);
panel1.add(jlblFinalExam);
panel1.add(jtfFinalExam);
// Assigns the text panel and the button to one panel
JPanel panel2 = new JPanel(new BorderLayout());
panel2.add(panel1, BorderLayout.CENTER);
panel2.add(jbtCreatePieChart, BorderLayout.SOUTH);
add(panel2, BorderLayout.WEST);
jbtCreatePieChart.addActionListener(new ButtonListener());
}
class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// Set the size and trigger a repaint
final PieChartGraphic pie = new PieChartGraphic();
add(pie, BorderLayout.CENTER);
pie.setPreferredSize(new Dimension());
pie.repaint();
}
}
class PieChartGraphic extends JPanel {
#Override
protected void paintComponent(Graphics slice) {
super.paintComponent(slice);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
int radius = (int) (Math.min(getWidth(), getHeight()) * 0.4);
int x = xCenter - radius;
int y = yCenter - radius;
double inputIsDouble;
int inputIsInt;
int availablePercentage = 100;
int currentAngle = 0;
ArrayList<JTextField> jtfs = new ArrayList<>();
jtfs.add(jtfProjects);
jtfs.add(jtfParticipation);
jtfs.add(jtfQuizzes);
jtfs.add(jtfFinalExam);
ArrayList<Color> color = new ArrayList<>();
color.add(Color.RED);
color.add(Color.GREEN);
color.add(Color.BLUE);
color.add(Color.WHITE);
for (int i = 0; i < jtfs.size(); i++) {
inputIsDouble = userInput(jtfs.get(i).getText(), availablePercentage);
inputIsInt = (int) (inputIsDouble * 3.6);
// Sets the color of the filled
slice.setColor(color.get(i));
// Sets the start point and size of the angle
slice.fillArc(x, y, 2 * radius, 2 * radius, currentAngle, inputIsInt);
currentAngle += inputIsInt;
availablePercentage -= inputIsDouble;
}
// Places the text strings
slice.setColor(Color.BLACK);
slice.drawString("Participation - " +
"\jtfParticipation.getText() + "%", 1 / 4 * x, 1 / 4 * y);
slice.drawString("Projects - " + jtfProjects.getText() + "%", 3 / 4 * x, 1 / 4 * y);
slice.drawString("Quizzes -- " + jtfQuizzes.getText() + "%", 1 / 4 * x, 3 / 4 * y);
slice.drawString("Final - " + jtfFinalExam.getText() + "%", 3 / 4 * x, 3 / 4 * y);
}
}
public static double userInput(String inputIsString, int availablePercentage) {
return new Double(inputIsString).doubleValue();
}
public static void main(String[] args) {
PieChart frame = new PieChart();
frame.setTitle("CMIS Pie Chart");
frame.setSize(334, 215);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);
}
}
Here are a few things to consider:
After creating panel3, the component sizes are never set:
panel3.setSize(200, 200);
PieChartGraphic pieChartGraphic = new PieChartGraphic();
pieChartGraphic.setSize(200, 200);
panel3.add(pieChartGraphic);
After adding jpanel3, you should call
jpanel3.repaint();
to paint the Graphics of the added component.
There is user input and validation happening half way through the paintComponent call. This should be done immediately before you do any painting, etc.
I've used:
public static double userInput(String inputIsString, int availablePercentage) {
return new Double(inputIsString).doubleValue();
}
and can see the Piechart.
I think you have a couple problems here.
First is the size/repaint problem #Reimeus pointed out. You need to set the size of the pie chart, and then cause it to be repainted.
Next, the way you add a new PieChartPanel with each button click seems an odd way to do things. You will end up creating new panels that are just stacked on top of each other each time the user presses the button. Why not just have the Pie chart panel permanently added, and just update what is displayed on it, depending on the state?
I changed the following bits of code. First I changed the action listener to remove the extra panel and set a size on the panel. I also added a repaint, although that doesn't seem to matter:
class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// Set the size and trigger a repaint
final PieChartGraphic pie = new PieChartGraphic();
add(pie, BorderLayout.EAST);
pie.setPreferredSize( new Dimension( 300, 300 ) );
pie.repaint();
}
}
I then simplified the paintComponent method to remove all of your code:
protected void paintComponent(Graphics slice) {
super.paintComponent(slice);
slice.setColor( Color.RED );
slice.fillRect( 0, 0, getWidth(), getHeight() );
}
Finally, I changed the JFrame to be resizable. This is an easy way during testing to trigger a repaint. With these changes, when I click on the button, I don't see anything, but if I resize the window, I see the red box.
Related
I'm making a score-keeping program, but I'm running into a problem. What I've tried to do is have a JPanel at the top that contains two JPanels, which, in turn, contains two team names. I'm confused as to why the two JLabels at the top of the program aren't centered inside of the JPanels they're contained in.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ScoreFrame extends JFrame {
private static final Dimension SCREEN_SIZE = Toolkit.getDefaultToolkit().getScreenSize();
private static final int WIDTH = SCREEN_SIZE.width;
private static final int HEIGHT = SCREEN_SIZE.height;
private final JTextField[] nameField = new JTextField[] { new JTextField(), new JTextField() };
private final JLabel[] nameLabel = new JLabel[] { new JLabel("Team 1"), new JLabel("Team 2") };
private final GridBagLayout gridBag = new GridBagLayout();
private final GridBagConstraints constraints = new GridBagConstraints();
private final JPanel topPanel = new JPanel();
public ScoreFrame() {
super();
setResizable(false);
setSize(SCREEN_SIZE);
setLayout(gridBag);
setUndecorated(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(new EscapeListener());
addComponents();
}
private void addComponents() {
addToTopPanel();
constraints.insets = new Insets(0, 0, (int) (HEIGHT * (double) 4 / 5), 0);
gridBag.setConstraints(topPanel, constraints);
add(topPanel);
}
private void addToTopPanel() {
final JPanel[] teamPanel = new JPanel[] { new JPanel(), new JPanel() };
topPanel.setLayout(gridBag);
topPanel.setSize(new Dimension(WIDTH, HEIGHT / 5));
Dimension teamPanelSize = new Dimension(WIDTH / 2, HEIGHT / 5);
teamPanel[0].setSize(teamPanelSize);
teamPanel[1].setSize(teamPanelSize);
Font nameFont = new Font("Times New Roman", Font.PLAIN, 50);
nameLabel[0].setFont(nameFont);
nameLabel[1].setFont(nameFont);
teamPanel[0].add(nameLabel[0]);
teamPanel[1].add(nameLabel[1]);
gridBag.setConstraints(teamPanel[0], constraints);
constraints.gridx = 1;
gridBag.setConstraints(teamPanel[1], constraints);
topPanel.add(teamPanel[0]);
topPanel.add(teamPanel[1]);
}
public void paint(Graphics g) {
super.paint(g);
int strokeSize = ((WIDTH + HEIGHT) / 2) / 300;
if (strokeSize < 1) {
strokeSize = 1;
}
final int fontSize = (int) (strokeSize * 12.5);
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(new BasicStroke(strokeSize));
g.drawLine(WIDTH / 2, 0, WIDTH / 2, HEIGHT / 5);
g.drawLine(WIDTH / 2, (int) (HEIGHT * (double) 105 / 400), WIDTH / 2, HEIGHT);
g.drawLine(0, HEIGHT / 5, WIDTH, HEIGHT / 5);
g.drawRect((int) (WIDTH * (double) 45 / 100), HEIGHT / 5, WIDTH / 10, (int) (HEIGHT * (double) 3 / 20));
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g.setFont(new Font("Times New Roman", Font.PLAIN, fontSize));
g.drawString("Errors", (int) (WIDTH * (double) 101 / 220), HEIGHT / 4);
}
private JFrame getFrame() {
return this;
}
public static void main(final String args[]) {
new ScoreFrame().setVisible(true);
}
public class EscapeListener implements KeyListener {
public void keyPressed(final KeyEvent event) {
if (event.getKeyCode() == 27) {
final int choice = JOptionPane.showConfirmDialog(getFrame(), "Do you want to exit the program?");
if (choice == 0) {
System.exit(0);
}
}
}
public void keyReleased(final KeyEvent event) {
}
public void keyTyped(final KeyEvent event) {
}
}
}
Invoking pack() is a critical step in using layouts. This example uses JLabel.CENTER and GridLayout to center the labels equally as the frame is resized. For simplicity, the center panel is simply a placeholder. This somewhat more complex example uses a similar approach along with java.text.MessageFormat.
Addendum: But how would I apply pack() to my code?
Simply invoke pack() as shown in the examples cited. I don't see an easy way to salvage your current approach of setting sizes extrinsically. Instead, override getPreferredSize() in a JPanel for your main content. No matter the screen size, your implementation of paintComponent() should adapt to the current size, for example.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/** #see https://stackoverflow.com/a/14422016/230513 */
public class Scores {
private final JLabel[] nameLabel = new JLabel[]{
new JLabel("Team 1", JLabel.CENTER),
new JLabel("Team 2", JLabel.CENTER)};
private void display() {
JFrame f = new JFrame("Scores");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel teamPanel = new JPanel(new GridLayout(1, 0));
teamPanel.add(nameLabel[0]);
teamPanel.add(nameLabel[1]);
f.add(teamPanel, BorderLayout.NORTH);
f.add(new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(320, 240);
}
}, BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Scores().display();
}
});
}
}
I need some help with my code; I have a program that will show the graph of Ohm's Law. The graph was showing before I put a save button. When i run the program, it will only show the everything except for the graph. Also, I have problems in saving the current and voltage array into a .txt file. Please help!
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.font.FontRenderContext;
import java.awt.font.LineMetrics;
import java.awt.geom.*;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import static java.nio.file.Files.newBufferedWriter;
import java.nio.file.StandardOpenOption;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class DrawGraph extends JPanel {
double current[] = new double [999];
double voltage[] = new double [999];
final int TEXT = 20;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int w = 400;
int h = 400;
g2.setStroke(new BasicStroke(3));
g2.drawLine(TEXT, TEXT, TEXT, h-TEXT);
g2.drawLine(TEXT, h-TEXT, w-TEXT, h-TEXT);
for(int x= 0; x<1000; x++ )
{
current[x]=x+1;
voltage[x]=x+1;
}
g2.setPaint(Color.red);
g2.setStroke(new BasicStroke(2));
g2.draw(new Line2D.Double(TEXT, h-TEXT, w-TEXT ,TEXT ));
// Draw labels.
g2.setPaint(Color.black);
Font font = g2.getFont();
FontRenderContext frc = g2.getFontRenderContext();
LineMetrics lm = font.getLineMetrics("0", frc);
float sheight = lm.getAscent() + lm.getDescent();
// Ordinate label.
g2.setFont(new Font("Century Gothic", Font.PLAIN, 15));
String s = "Voltage V";
float sY = TEXT + ((h - 2*TEXT) - s.length()*sheight)/2 + lm.getAscent();
for(int r = 0; r < s.length(); r++)
{
String letter = String.valueOf(s.charAt(r));
float swidth = (float)font.getStringBounds(letter, frc).getWidth();
float sX = (TEXT - swidth)/2;
g2.drawString(letter, sX, sY);
sY += sheight;
}
// Abcissa label.
s = "Current A";
sY = h - TEXT + (TEXT - sheight)/2 + lm.getAscent();
float swidth = (float)font.getStringBounds(s, frc).getWidth();
float sX = (w - swidth)/2;
g2.drawString(s, sX, sY);
//Gridlines
int b=TEXT+(((w-TEXT)-TEXT)/10);
g2.setPaint(Color.gray);
for(int a=1; a<=10; a++)
{
b+=36;
g2.setStroke(new BasicStroke(1));
g2.drawLine(b, h-TEXT, b, TEXT);
g2.drawLine(TEXT, b, w-TEXT, b);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Ohm's Law");
JPanel panel = new JPanel(new BorderLayout(3,1));
JPanel titlepanel = new JPanel();
titlepanel.setPreferredSize(new Dimension(400,50));
JLabel title = new JLabel("OHM'S LAW");
title.setFont(new Font("Century Gothic", Font.BOLD, 25));
titlepanel.add(title);
panel.add(titlepanel,BorderLayout.NORTH);
JPanel graphpanel = new JPanel();
graphpanel.setBackground(Color.white);
graphpanel.setPreferredSize(new Dimension(420,420));
DrawGraph drawgraph = new DrawGraph();
graphpanel.add(drawgraph);
panel.add(graphpanel,BorderLayout.CENTER);
JPanel buttonpanel = new JPanel ();
buttonpanel.setPreferredSize(new Dimension(400,50));
JButton save = new JButton("SAVE");
save.addActionListener(
new ActionListener()
{
#Override
public void actionPerformed (ActionEvent event)
{
JFrame parentFrame = new JFrame();
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("Specify a file to save");
int userSelection = fileChooser.showSaveDialog(parentFrame);
if (userSelection == JFileChooser.APPROVE_OPTION)
{
java.io.File fileToSave = fileChooser.getSelectedFile();
try
{
fileToSave.createNewFile();
try (BufferedWriter writer = newBufferedWriter(fileToSave.toPath(), Charset.defaultCharset(), StandardOpenOption.WRITE))
{
writer.write("V=I\t R=1\r Voltage \t Current\n");
//writer.write("Material: " + material.getSelectedValue().toString()+"\r\nv = " + v + "\r\nE1 = " + e1 + "\r\nE2 = " + e2);
}
}
catch (IOException ex)
{
Logger.getLogger(DrawGraph.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Save as file: " + fileToSave.getAbsolutePath());
}
}
}
);
save.setFont(new Font("Century Gothic", Font.BOLD, 15));
buttonpanel.add(save);
panel.add(buttonpanel, BorderLayout.SOUTH);
frame.add(panel);
frame.getContentPane().setBackground(Color.GREEN);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGui();
}
});
}
}
JPanel graphpanel = new JPanel();
graphpanel.setBackground(Color.white);
graphpanel.setPreferredSize(new Dimension(420,420));
DrawGraph drawgraph = new DrawGraph();
graphpanel.add(drawgraph);
panel.add(graphpanel,BorderLayout.CENTER);
You add your DrawGraph component to a JPanel. By default a JPanel uses a FlowLayout() which respects the preferred size of any component added to it. Your custom DrawGraph component has a preferred size of 0, so there is nothing to paint.
Every Swing component is responsible for determining its own preferred size so you need to override the getPreferredSize() method of your DrawGraph components to return its preferred size so the layout manager can do its job.
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
Also, don't use setPreferredSize(). The layout manager will determine the preferred size of the panel based on the components added to it.
First things first. Make a JFrame derived class and in that class insert separately your buttonPanel which extends JPanel on the BorderLayout.SOUTH and your DrawGraph panel on the BorederLayout.Center. Don't add butttonPanel to the window you are drawing in.
I also suggest to change name from DrawGraph to GraphPanel you can do it just by clicking on any reference to the class and hitting alt+shift+r if you use Eclipse IDE.
So to conclude:
public class MainWindow extends JFrame(){
public void createGUI(){
add(graphPanel = new GraphPanel(), BorderLayout.CENTER);
add(buttonPanel = new JPanel(), BorderLayout.SOUTH);
}
}
and build your solution around that.
I need to draw a square, from user input. After the user input, a frame pops up, and a button says "click me". I need the click to generate the square.
How do I make the button generate the square when I click it?
UPDATE
my code is as follows!
import javax.swing.*;
import java.util.*;
import java.awt.event.*;
import java.awt.Color;
import java.awt.*;
//All of these imports are required, in the case of BorderLayout, and JFrame, etc.
public class Gooey implements ActionListener // implements the ActionListener (the button click)
{
private static int n; // make the n variable as in the lab, used for height and width of square
private static JFrame frame; //make the frame non-accessible from any other classes, simply because
// we don't want a bunch of frames running with the same stuff!
public static void main(String[] args)
{
frame = new JFrame(); //create the frame! DUH!
JButton button = new JButton("DrawSquare!"); //make the button!
button.addActionListener(new Gooey()); //adds the actionListener to it can respond to a button click
JLabel label = new JLabel("Draw Your Square!"); //Make the label set to DrawSquare
JPanel panel = new JPanel();
panel.add(button); //add the button to the panel!
panel.add(label); // add the label to the panel!
frame.getContentPane().add(panel, BorderLayout.NORTH); //set the panel of the frame to the "north"
Scanner user_input = new Scanner(System.in);
System.out.println("Enter The Size Of Your Square. Make sure it's not too big!!");
n = user_input.nextInt(); //set 'n' to equal the width and height of the drawSquare method
int FRAME_WIDTH = (n + 50); //make sure the width fits the square
int FRAME_HEIGHT = (n + 100); // make sure the height fits the square
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); //set the frame width and height, to fit square.
frame.setTitle("A nice "
+ n
+ " by "
+ n
+ " Square!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //make sure the frame exits and resets when closed.
frame.setVisible(true); //make it visible on the foreground!
}
#Override //recommended. Keeps from making program all wacky!
public void actionPerformed(ActionEvent arg0) {
JPanel p = new JPanel() //obviously, a new JPanel!
{
protected void paintComponent(Graphics g) //start making the square itself, and color it !!!
{
super.paintComponent(g);
int height = n;
int width = n;
g.setColor(Color.blue);
g.drawRect(10, 10, height, width);
};
};
frame.getContentPane().add(p, BorderLayout.CENTER); //center the Square inside the frame.
frame.getContentPane().revalidate(); //Recalculate the layout.
}
}
This is finished!
1)Read more about custom Paintings. Do your paintings in paintComponent(Graphics g) method of JPanel for example.
2)Your FrameViewer haven't paint(Graphics g) method because of you can't override it.
3)Your FrameViewer implements ActionListener but you don't override actionPerformed() because you get compilation error.
4) You button do nothing, you forgot to add an ActionListener to that.
I fixe your code, examine it:
public class Form implements ActionListener {
private static int n;
private static JFrame frame;
public static void main(String[] args) {
frame = new JFrame();
JButton button = new JButton("Click Me!");
button.addActionListener(new Form());
JLabel label = new JLabel("DrawSquare");
JPanel panel = new JPanel();
panel.add(button);
panel.add(label);
frame.getContentPane().add(panel,BorderLayout.NORTH);
Scanner user_input = new Scanner(System.in);
System.out.println("Enter The Size Of Your Head! Or Square. Whichever!");
n = user_input.nextInt();
int FRAME_WIDTH = (n + 600);
int FRAME_HEIGHT = (n + 400);
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle("A nice "
+ n
+ " by "
+ n
+ " Square! Just click the button and watch the instantanious magic!");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent arg0) {
JPanel p = new JPanel(){
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int height = n;
int width = n;
g.setColor(Color.blue);
g.drawRect(10, 10, height, width);
};
};
frame.getContentPane().add(p,BorderLayout.CENTER);
frame.getContentPane().revalidate();
}
}
I know there have been many topics on this subject before and I have used Google extensively to figure this out, but whatever I do I cannot get two panels to display in one JFrame. I have tried many things including CardLayout but that didn't seem to work. I have a feeling this is a very easy solution..
The purpose is to see the difference between the two panels due to the random positioning.
Here are some of the java files (only pertinent code - there is also a Snowman.java but it just provides the drawing for the snowmen similar to ghost.java):
Ghost.java
import java.awt.*;
public class Ghost
{
private int x, y;
private String name;
private boolean happy;
private Color color;
public Ghost (Color shade, int upperX, int upperY, String a, boolean b)
{
color = shade;
x = upperX;
y = upperY;
name = a;
happy = b;
}
public void draw (Graphics page)
{
page.setColor(color);
page.fillOval (x, y, 50, 125);
page.fillRect (x+1, y+60, 49, 75); // body of ghost
page.setColor(Color.black);
page.fillOval (x+12, y+10, 8, 8);
page.fillOval (x+32, y+10, 8, 8); // eyes
page.setColor(Color.white);
page.drawString(name, x+8, y-5); // name
page.setColor(Color.black);
if (happy == true)
page.fillArc (x+10, y+30, 33, 10, 180, 180);
else
page.fillArc (x+10, y+30, 33, 10, 0, 180); // smile/frown
}
public void setColor (Color shade)
{
color = shade;
}
public void setX (int upperX)
{
x = upperX;
}
public void setY (int upperY)
{
y = upperY;
}
HalloweenPanel.java :
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class HalloweenPanel extends JPanel
{
private Ghost ghost1, ghost2, ghost3;
private Snowman snowman1, snowman2;
public HalloweenPanel()
{
setBackground (Color.black);
Random rand = new Random();
int randomX = rand.nextInt(700)+50;
int randomY = rand.nextInt(400)+50;
boolean randomHappy = (Math.random() < 0.5);
boolean randomHappy2 = (Math.random() < 0.5);
ghost1 = new Ghost (Color.white, randomX, randomY, "Scary", randomHappy2);
ghost2 = new Ghost (Color.blue, randomX, 100, "Happy", true);
ghost3 = new Ghost (Color.yellow, 300, randomY, "Scared", randomHappy);
snowman1 = new Snowman (500, 50);
snowman2 = new Snowman (750, 100);
}
public void paintComponent (Graphics page)
{
Random rand = new Random();
int randomX2 = rand.nextInt(900);
int randomY2 = rand.nextInt(500);
super.paintComponent(page);
ghost2.setX(randomX2);
ghost3.setY(randomY2);
ghost1.draw(page);
ghost2.draw(page);
ghost3.draw(page);
snowman1.draw(page);
snowman2.draw(page);
}
}
HalloweenDriver.java:
import javax.swing.*;
import java.awt.*;
public class HalloweenDriver
{
public static void main (String[] args)
{
JFrame frame = new JFrame ("Halloween - Winter is Coming..");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
HalloweenPanel panel = new HalloweenPanel();
HalloweenPanel panel2 = new HalloweenPanel();
mainPanel.setLayout(new GridLayout(1,0));
mainPanel.add(panel);
mainPanel.add(panel2);
frame.add(mainPanel);
frame.pack();
frame.setVisible(true);
}
}
frame.getContentPane().add(panel);
frame.getContentPane().add(panel2);
You are trying to add two panels to the CENTER of a BorderLayout. This can't be done.
Try:
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.getContentPane().add(panel2, BorderLayout.SOUTH);
to see the difference.
If this isn't what you want then try another layout manager. Read the Swing tutorial on Layout Managers.
Or, if you are trying to stack the two panels on top of one another (on the Z axis) then try the OverlayLayout. This is not covered in the tutorial so you will need to look at the API. You will also need to make the "top" panel non-opaque() so it doesn't paint over top of the bottom panel.
I get a JFrame and i want to display a JLabel with a border in it with a padding of maybe 50px. When i set the size of the JFrame to 750, 750, and the size of the JLabel to 650, 650 and the location to 50, 50, it display it strange... Here's my code:
public class GUI {
/**
* Declarate all
*/
public int height = 750;
public int width = 750;
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (screen.width / 2) - (width / 2); // Center horizontally.
int y = (screen.height / 2) - (height / 2); // Center vertically.
/**
* Create the GUI
*/
JFrame frame = new JFrame();
Border border = LineBorder.createBlackLineBorder();
JLabel label = new JLabel();
public GUI(){
label.setBorder(border);
label.setSize(700, 700);
label.setLocation(0, 0);
frame.getContentPane().setLayout(null);
frame.add(label);
}
public void createGUI() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(x,y,width,height);
frame.setVisible(true);
}
}
So I think the title-bar at the top is also include in the size. In Graphics you can use getInsets(). Now is there anything like that for Swing / JFrame?
First get the pixels trimmed out by the frame.
int reqWidth = reqHeight = 750;
// first set the size
frame.setSize(reqWidth, reqHeight);
// This is not the actual-sized frame. get the actual size
Dimension actualSize = frame.getContentPane().getSize();
int extraW = reqWidth - actualSize.width;
int extraH = reqHeight - actualSize.height;
// Now set the size.
frame.setSize(reqWidth + extraW, reqHeight + extraH);
An alternate simpler way. The previous works but this is recommended.
frame.getContentPane().setPreferredSize(750, 750);
frame.pack();
Hope this helps.
EDIT:
Add this in your constructor before adding components to the frame. and to set it in the middle, use
frame.setLocationRelativeTo(null);
This will center the window on the screen.
Using setPreferredSize() is problematic, as it always overrules the component's calculation with an arbitrary choice. Instead, pack() the enclosing Window to accommodate the preferred sized of the components, as shown below.
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
/**
* #see https://stackoverflow.com/a/13481075/230513
*/
public class NewGUI extends JPanel {
private static final int S1 = 10;
private static final int S2 = 50;
private JLabel label = new JLabel("Hello, world!");
public NewGUI() {
label.setHorizontalAlignment(JLabel.CENTER);
Border inner = BorderFactory.createEmptyBorder(S1, S1, S1, S1);
Border outer = BorderFactory.createLineBorder(Color.black);
label.setBorder(new CompoundBorder(outer, inner));
this.setBorder(BorderFactory.createEmptyBorder(S2, S2, S2, S2));
this.add(label);
}
private void display() {
JFrame f = new JFrame("NewGUI");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new NewGUI().display();
}
});
}
}