I wrote a program that draws triangles on the screen. However only the first triangle is shown. How can I make multiple custom JComponents visible?
I already tried to create something like a draw() method but then I can't perform any actions on this object like i. e. I would like the color of the triangle to change whenever I click on it. For this I would need a MouseListener but it won't work with the draw() method.
View.java file:
package test;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class View extends JPanel {
public View()
{
setPreferredSize(new Dimension(300, 300));
add(new Triangle(20, 50, Color.red)); //this one will react to mouseClicked
add(new Triangle(100, 200, Color.pink)); //this one doesn't appear
}
public static void main(String []args)
{
JFrame frame = new JFrame("Trianlge test");
frame.add(new View());
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Triangle p3 = new Triangle(60, 120, Color.blue); //this one won't react to mouseClicked()
p3.draw(g);
}
}
Triangle.java file:
package test;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.GeneralPath;
import javax.swing.JComponent;
public class Triangle extends JComponent implements MouseListener{
private int x,y;
private Color c;
public Triangle(int x, int y, Color c)
{
this.x = x;
this.y = y;
this.c = c;
setPreferredSize(new Dimension(100, 100));
addMouseListener(this);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
GeneralPath path = new GeneralPath();
g2d.setColor(c);
path.moveTo(x, y);
path.lineTo(x, y);
path.lineTo(x+50, y);
path.lineTo(x, y-50);
path.closePath();
g2d.fill(path);
repaint();
}
public void draw(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
GeneralPath path = new GeneralPath();
g2d.setColor(c);
path.moveTo(x, y);
path.lineTo(x, y);
path.lineTo(x+50, y);
path.lineTo(x, y-50);
path.closePath();
g2d.fill(path);
repaint();
}
#Override
public void mouseClicked(MouseEvent e) {
c = Color.cyan;
repaint();
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
JFrame frame = new JFrame();
First of all that statement in your View class is completely unnecessary. You would not create a JFrame instance in the constructor of a component. Also your code never references the variable which is a good indication it is not needed.
However, the main problem is your concept of creating custom components is wrong:
setPreferredSize(new Dimension(100, 100));
You attempt to set the preferred size of the component.
add(new Triangle(100, 200, Color.pink)); //this one doesn't appear
But then you attempt to do you custom painting at (100, 200) which is outside the size of the component. So the painting logic clipped at the size of component so you don't see anything being painted.
Custom painting should be done relative to (0, 0) of the component, not relative to the parent component.
If you you want to randomly position components on the parent panel then you need to:
set the parent panel to use a null layout
set the location of each component you add to the panel
set the size of each component you add to the panel.
basically you need to take over the functionality of the layout manager.
Other problems with your current painting code:
Don't invoke repaint() in a painting method. This will essentially cause an infinite painting loop. If you need animation you use a Swing Timer to schedule the animation.
Don't invoke paintComponent(...) directly. Swing will invoke paintComponent() when a component needs to be repainted.
However, I would suggest that if you want to paint Shapes on a panel, Then you forget about creating custom components. Instead you keep an ArrayList of the Shapes you want to paint and then in the paintComponent() method of the panel you iterate through the ArrayList to paint each shape.
For an example of this approach take a look at the Draw On Component example found in Custom Painting Approaches.
Note:
If you really want to be able to handle mouse events then you need to use a Shape object to represent your shapes to do proper hit detection. If you just display your shape as a component, then the mouse hit will be detected if you click anywhere in the rectangular area of the component, not just the triangle part that you actually paint. The Shape class has a contains(...) method you can use to determine if you actually click in the Shape or not.
Check out Playing With Shapes for more information on this concept.
Set a border to Triangle components like this:
public Triangle(int x, int y, Color c)
{
this.x = x;
this.y = y;
this.c = c;
setPreferredSize(new Dimension(100, 100));
addMouseListener(this);
// Set this border to see the boundaries of this component.
// When you are done, you may remove this.
setBorder(BorderFactory.createLineBorder(Color.black));
}
Then you can better understand the bounds of the components.
Pink triangle is not visible because it is outside component's boundary.
p3 triangle does not react to mouse clicks because it is just a drawing. Only components react to mouse and other events.
Notice that components are rectangle in shape. So, the mouse listener you have added works anywhere on the component; not only on the area of triangle.
You are drawing triangles in two ways in this program.
1. By adding Triangle components. (Like "add(new Triangle(20, 50, Color.red));")
2. By drawing p3 in paintComponent() method.
From software designing perspective, better to stick to one approach. Otherwise it can be confusing and error prone.
Related
So in the past few days I've tried to implement an easier version of a graph plotter.
One big problem I was confronted with was a bug that occured on repainting.
Basically I've designed my program in one class which is responsible for drawing the whole coordinate system and the given function after clicking a JButton in an other class. The other class contains the JButton which is pressed. After pressing the JButton it calls a function in the coordinate system class which repaints the picture. Both of those classes are extending JPanel.
The bug was that when I was doing the repainting on pressing the button, the button was drawn on the coordinate System and not in its original place, so in other words on the other JPanel even though I didn't change a thing about placements and stuff. Both classes were added to a JFrame which use a GridLayout.
Can anyone tell me why super.paintComponent(g); solved that bug?
Edit: Added Code
Window class
public class main {
public static void main(String[] args) throws SemanticFailureException {
int x = 800;
int y = 600;
JFrame frame = new JFrame();
frame.setLayout(new GridLayout());
frame.setTitle("Function plotter");
frame.setSize(2*x, 2*y);
Surface test = new Surface(x, y, 10);
CommandDraw test1 = new CommandDraw(x/2,y,test);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(test);
frame.add(test1);
frame.setVisible(true);
}
}
Coordinate System class: (changed drawing the coordinate system to a rectangle for simplicity, the bug still occures with only drawing a rectangle)
public class Surface extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
boolean drawFunct;
public Surface(int x1, int y1, int coordLength) {
setSize(x1,y1);
drawFunct = false;
}
public void paintComponent(Graphics g) {
super.paintComponent(g); // without this the jbutton occures on the left
// create Graphics object to get more functions
Graphics2D g2 = (Graphics2D) g;
// draw Plotter
drawFunction(g2);
if (drawFunct)
g2.drawLine(0, 0, 80, 80);
}
public void drawFunction(Graphics2D g) {
g.drawRect(40, 40, 30, 30);
}
public void redraw() {
drawFunct = true;
repaint();
}
}
The Class with the JButton:
public class CommandDraw extends JPanel {
/**
*
*/
private static final long serialVersionUID = 1L;
JButton makeDraw;
JTextField inputPoly;
Surface surf;
public CommandDraw(int x, int y, Surface surf) {
this.surf = surf;
setSize(x,y);
setLayout(new FlowLayout());
makeDraw = new JButton("draw Function");
makeDraw.setBackground(Color.LIGHT_GRAY);
makeDraw.setFocusable(false);
makeDraw.addActionListener( new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
surf.redraw();
}
});
add(makeDraw);
inputPoly = new JTextField("Input polynomial");
inputPoly.setHorizontalAlignment(JTextField.CENTER);
add(inputPoly);
}
}
Can anyone tell me why super.paintComponent(g); solved that bug?
Because the call to paintComponent(g) of the superclass (JPanel) will guarantee that panel will be rendered as expected before you do your paint operations. You need to make sure that your JPanel will behave, in the Graphics perspective, like any other JPanel.
A template for a customized JPanel to draw should be something like:
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class MyDrawPanel extends JPanel {
#Override
protected void paintComponent( Graphics g ) {
super.paintComponent( g );
// create a new graphics context based on the original one
Graphics2D g2d = (Graphics2D) g.create();
// draw whatever you want...
g2d.dispose();
}
}
EDIT
You need to call super.paintComponent(g) to tell that the JPanel paintComponent(Graphics) version should be execute before you start doind your customized things. It's something like to ask the JPanel to prepare its paint capabilities to be used. A good starting point to these kind of doubts is the documentation: https://docs.oracle.com/javase/10/docs/api/javax/swing/JComponent.html#paintComponent(java.awt.Graphics)
The dispose() method is being called in the copy of the original Graphics. If you dispose the Graphics that is passed to the method, you may have some issues too. You could use the original Graphics to perform you painting operations, but you shouldn't, so a better practice is to make a copy of the original Graphics and dispose it after using.
Take a look here too: How does paintComponent work?
I have a class called CharMove,in it are the paint(Graphics g) method, and some custom methods. The class should create a square,then move that square randomly around the screen. However,when I create two instances of this class in my World Class,only one square appears. First the square doesn't move but the new coord.'s are displayed,then after 5 runs the square begins to move randomly. I think the program is getting caught on the Graphics method because only one square is being created,when the CharMove class should be creating another instance of Graphics.I have searched online but can't find a way to create different instances of Graphics.Thanks in advance.
CharMove Class
import java.awt.*;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
import java.util.Random;
public class CharMove extends JPanel {
int x = 250;
int y = 250;
public void paint(Graphics g) {
Graphics pane = (Graphics2D) g;
pane.setColor(Color.blue);
pane.fillRect(x, y, 10, 10);
}
public void movement(JFrame frame) {
for (int i=0;i<5;i++) {
try {
TimeUnit.SECONDS.sleep(1);
this.x = Getx(this.x,frame);
this.y = Gety(this.y,frame);
frame.repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public int Getx(int a, JFrame frame) {
Random rn = new Random();
int xnum = rn.nextInt(10)-5;
a += xnum;
System.out.println("x:" + a);
return a;
}
public int Gety(int b, JFrame frame){
Random rn = new Random();
int ynum = rn.nextInt(10)-5;
b += ynum;
System.out.println("y:" + b);
return b;
}
}
World Class
import java.awt.*;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
import java.util.Random;
public class World {
public static void main(String[] args) {
JFrame game = new JFrame();
game.setTitle("Matrix");
game.setSize(500, 500);;
game.getContentPane().setBackground(Color.white);
game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.setVisible(true);
CharMove char1 = new CharMove();
CharMove char2 = new CharMove();
game.add(char1);
game.add(char2);
char1.movement(game);
char2.movement(game);
}
}
In swing, all of your painting should be down in paintComponent(Graphics g) (rename your method)
To do animation, you should use a Swing Timer (w/ an ActionListener) to update the positions of your animated items. Once that's done, the timer should call repaint();
public void actionPerformed(ActionEvent ae) {
this.x = Getx(this.x,frame);
this.y = Gety(this.y,frame);
frame.repaint();
}
However,when I create two instances of this class in my World Class,only one square appears.
The default layout manager for a JFrame is a BorderLayout.
game.add(char1);
game.add(char2);
When you add components without specifying a constraint then both components are added to the CENTER. However, only one component can be added to the CENTER so only the last one added is displayed.
Try:
game.add(char1, BorderLayout.PAGE_START);
game.add(char2, BorderLayout.PAGE_END);
However when you do this the componens won't be displayed because they have a (0, 0) preferredSize. So you will also need to override the getPreferredSize() method of your CharMove class.
#Override
public Dimension getPreferredSize()
{
return new Dimension(300, 200);
}
Also, custom painting should be done in the paintComponent(...) method and you need to invoke super.paintComponent(...) at the start to clear the background.
The repaint() method in your movement() method should be on the panel, not the frame, since you are changing properties of the panel.
Each CharMove is essentially a JPanel which draws a single square of size 10 somewhere on itself when it is painted. You are adding two CharMove panels to the game JFrame (which in fact adds them to the default content pane, which has a subclassed BorderLayout). As you are not providing a layout constraints object, in fact both panels are being added to the BorderLayout.CENTER of the content pane, and the second is completely covering the first.
To correct this you should modify CharMove so that it paints all of the squares (eg by maintaining an array or some sort of collection of squares, and painting all of them in the paint method) and just add that one panel to the JFrame.
Apart from this issue, while you are animating the squares in the movement method you are blocking the Event Dispatch Thread, meaning that during the animation you won't be able to move any other windows or respond to any mouse clicks or other inputs. Take ControlAltDel's advice about using the Swing Timer for animation to correct this problem.
I'm trying to write some custom painting code. Specifically, I want to have a bunch of extended JPanels which paint different aspects of my GUI, but each of these extended panels holds the instructions for how it is to be painted.
I've created the code, but for some reason, the extended JPanel isn't being painted on the main JPanel in my JFrame regardless of what I do. Here is a gist of my main class and one of my extended JPanels. What am I missing?
Breakout
//Java imports
import javax.swing.JFrame;
import java.awt.Dimension;
import javax.swing.JPanel;
//Personal imports
import Ball;
public class Breakout {
public static void main (String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {//start the GUI in a new thread
public void run(){
showGUI();
}
});
}
private static void showGUI() {
JFrame frame = new JFrame("Breakout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension d = new Dimension(640,480);
frame.setMinimumSize(d);
frame.setResizable(false);
JPanel p = new JPanel();
p.add(new Ball(200,200,50,255,0,0));
frame.add(p);
frame.setVisible(true);
}
}
Ball
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
public class Ball extends JPanel {
public int x;
public int y;
public int radius;
public Color colour;
public Ball(int x, int y, int radius, int r, int g, int b) {
super();
this.x = x;
this.y = y;
this.radius = radius;
colour = new Color(r,g,b);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
//define constants
int topLeftX = x+radius;
int topLeftY = y+radius;
int diameter = radius *2;
//draw outline
g.setColor(Color.BLACK);
g.drawOval(topLeftX, topLeftY, diameter, diameter);
//fill it in
g.setColor(colour);
g.fillOval(topLeftX, topLeftY, diameter, diameter);
}
}
Using JPanels in this way is going to cause you no end of problems.
The two main problems you have are...
JPanels already have an idea of size and position, adding another x/y coordinate is just confusing and could lead you to painting off the components viewable space
The default preferred size of a JPanel is 0x0. This means when you add it another JPanel, using FlowLayout, the panel is given a size of 0x0, so nothing gets painted.
Instead, create an interface which has a method called paint and takes a Graphics2D object.
For each shape you want to paint, create a new class which implements this interface and use it's paint method to paint the object as you see fit.
Create a custom component, extending from JPanel and maintain a List of these shapes. In it's paintComponent, use a for-loop to paint each shape in the List.
This custom component should then be added to your frame...
In your showGUI method in your main class you have this code:
JPanel p = new JPanel();
p.add(new Ball(200,200,50,255,0,0));
frame.add(p);
This code creates a new JPanel then adds another JPanel to that. This is incorrect because it simply does not make sense to add another JPanel to a perfectly good JPanel that you just created. Instead just do this:
frame.getContentPane().add(new Ball(200, 200, 50, 255,0,0));
Or if you prefer:
Ball ball = new Ball(200, 200, 50, 255,0,0);
frame.getContentPane().add(ball);
I have a problem with put drawn circle into middle of Frame by using methods getWidth() and getHeight(). I tried something with Image package but no idea where to implement this methods:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Frame;
import java.awt.Image;
public class Circle extends Frame {
public Circle() {
setSize(400,400);
setLocationRelativeTo(null);
setVisible(true);
}
public Color() {
}
public void paint(Graphics g) {
g.setColor(Color.ORANGE);
g.fillOval(200, 200, 200, 200);
}
public static void main(String[] args) {
Circle c = new Circle();
c.paint(null);
}
}
Then I have to use method setColor(Color) and Color class constructor to make random color of this circle (after every run of this program). I opened Color constructor but there is an error :/
Better to extract all the paint functionality to a JComponent here to take full advantage of Swing's optimized paint model using paintComponent.
The Circle is actually a JFrame. Inside in its constructor, a new component is created which handles the painting of the circle. The Color constructor has been removed as this is invalid syntax.
The circle co-ordinates are start in the top left-hand corner and take the full available width & height for drawing.
Also would recommend using lightweight Swing components over old-style AWT component.
public class Circle extends JFrame {
public Circle() {
setSize(400, 400);
add(new CirclePanel());
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
Circle c = new Circle();
}
}
class CirclePanel extends JComponent {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.ORANGE);
g.fillOval(0, 0, getWidth(), getHeight());
}
}
See: Painting in AWT and Swing
Simply call getWidth() and getHeight() from within the paint(...) method and use the results returned for your fillOval(...) parameters.
But having said that, it's a better idea to draw in a Canvas that is added to the Frame. And having said that, it's much better still to draw in the paintComponent(...) method of a JPanel that is added to the contentPane of a JFrame in a Swing application.
I'm new to java. I do have a java class but I want to get ahead. I really like it! This is my problem. I'm trying to draw the two paddles needed for the game. I did create 2 objects for them, and they both "Show" but the following happens:
Main Runner
import javax.swing.JFrame;
public class PongRunner {
public static void main (String[] args)
{
new PongRunner();
}
public PongRunner()
{
JFrame PongFrame= new JFrame();
PongFrame.setSize(800,600);
PongFrame.add(new PaddleB());
PongFrame.add(new PaddleA());
PongFrame.setLocationRelativeTo(null);
PongFrame.setTitle("My Pong Game");
PongFrame.setResizable(false);
PongFrame.setVisible(true);
PongFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
PaddleA and PaddleB are both drawRect Graphics and draw a specific rectangle.
The graphics that I tell JFrame to add first are the only ones visible. The one under it doesnt get added into the Frame I wanted to know why,and how i can draw both paddles in the same JFrame... I'm reading my book and looking over the internet as much as possible, but no luck within these 2 days. Some help would be nice. I just started learning java and I think I'm making progress. Some tips would be nice too thanks :), specialy on actionListener since im going to have to use them to move the paddles!
SOURCE CODE OF BOTH PADDLES:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class PaddleA extends JPanel implements ActionListener
{
private Timer timer;
public void timer()
{
timer = new Timer(25, this);
timer.start();
}
public void actionPerformed(ActionEvent e)
{
repaint();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.RED);
g.fillRect(70,200,20,100);
}
}
PaddleB:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class PaddleB extends JPanel implements ActionListener
{
private Timer timer;
public void timer()
{
timer = new Timer(25, this);
timer.start();
}
public void actionPerformed(ActionEvent e)
{
repaint();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(500, 200, 20, 100);
}
}
As you've added the 2 paddles into the same BorderLayout.CENTER location of the main PongFrame, only the second paddle will be displayed.
This type of painting is more easily done using one Graphics object on one JComponent.
Swing components aren't really designed to be used like this. Each of your paddle JPanels is trying to paint a rectangle, but the container (the JFrame) and its layout manager will control the size and location of the JPanels. So the rectangle they paint may be outside their bounds, and won't appear at all.
Some Layout Managers will only show one of the JPanels if you add them one after another like this - see answer by Reimus.
To do animated graphics like this, you probably need to start with a single JComponent (e.g. a JPanel) that fills the JFrame, and paint both paddles as rectangles onto it.
This is because you add the first paddle and then add the second paddle over the first thus replacing them:
PongFrame.add(new PaddleB());
PongFrame.add(new PaddleA());
try using LayoutManagers here is just a quick sample:
PongFrame.getContentPane().add(new PaddleB(),BorderLayout.WEST);
PongFrame.getContentPane().add(new PaddleA(),BorderLayout.EAST);
also your g.fillRect(...); has x and y co-ordinates that are too large for the JFrame and thus are not displayed. Change it like so:
g.fillRect(0,0, 20, 100);
Not related though:
dont use JFrame.add() rather JFrame.getContentPane().add()
UPADTE:
As others have mentioned the logic for the game is a bit off. You should have a single drawing panel which is added to the JFrame and all drawing is done on the single JPanel using Graphics and not JPanels. Here is a small example:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class PongRunner {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new PongRunner();
}
});
}
public PongRunner() {
JFrame PongFrame = new JFrame();
PongFrame.setTitle("My Pong Game");
PongFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
PongFrame.setResizable(false);
PongFrame.setSize(400,400);
//PongFrame.setLocationRelativeTo(null);
PongFrame.getContentPane().add(new DrawingPanel());
PongFrame.setVisible(true);
}
}
class DrawingPanel extends JPanel {
Rect rect1, rect2;
public DrawingPanel() {
super(true);
rect1 = new Rect(80, 80, 20, 100, Color.yellow);
rect2 = new Rect(100, 200, 20, 100, Color.red);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(rect1.getColor());
g.fillRect(rect1.getX(), rect1.getY(), rect1.getWidth(), rect1.getHeight());
g.setColor(rect2.getColor());
g.fillRect(rect2.getX(), rect2.getY(), rect2.getWidth(), rect2.getHeight());
}
}
class Rect {
private Color color;
private int x, y, height, width;
Rect(int x, int y, int width, int height, Color color) {
this.x = x;
this.y = y;
this.height = height;
this.width = width;
this.color = color;
}
public Color getColor() {
return color;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Rectangle getBounds() {
return new Rectangle(x, y, width, height);
}
}
Please note this snippet is not perfect and merely demonstrates the stereotypical logic needed for drawing rectangles to form a game of sorts
I don't have time to try running your code, but try setting the size and position of the "paddle" objects, or set them as non-opaque. I believe that Swing tries to speed up rendering by not drawing components which are completely covered by another opaque component. It may not be drawing one of your paddles for that reason.
If you do set the size and position of your paddles, you may have to modify your paintComponent methods: if my memory is correct, I think the Graphics object which is passed in is clipped to the area of the component, so 0,0 would be the top-left corner of the component.
you shouldn't add your JPanels to your JFrame by the JFrame#add(Component) method. Better add them to the contentPane: frame.getContentPane().add(panel); You should although read about LayoutManagers. They can help you by positining Components in your Frame or mess things up if you use them incorrect.