first of all hi everyone!
I'm having a big problem with this: i need to build a program which consist in building a java swing interface that contains 5 squares, and one button. The button function is to draw a circle inside the squares. I have this code, but i dont know how to continue.
The Frame class:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
public class Window extends JFrame{
private static Pane pane;
private Window(){
setResizable(false);
setVisible(true);
setBounds(0,0,350,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args){
Window window = new Window();
window.setLocationRelativeTo(null);
pane = new Pane();
window.add(pane);
}
}
The pane class:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JLayeredPane;
public class Pane extends JPanel implements ActionListener{
private JButton next;
public Pane(){
setBounds(0,0,350,200);
setVisible(true);
setLayout(null);
repaint();
next = new JButton("Next");
next.setBounds(125,125,100,30);
next.addActionListener(this);
add(next);
}
public void actionPerformed (ActionEvent e){
Object source = e.getSource();
if (source == next){
Graphics g = this.getGraphics();
drawing(g);
}
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawRect(50,50,50,50);
g.drawRect(100,50,50,50);
g.drawRect(150,50,50,50);
g.drawRect(200,50,50,50);
g.drawRect(250,50,50,50);
}
private int times = 0;
public void drawing(Graphics g){
if(times<5){
g.setColor(Color.RED);
g.fillOval(50+times*50, 50, 50, 50);
times++;
}
}
}
I have this problems and questions:
Thank you very much everyone!
THere are some thingies, that you not doing in the right sense.
JFrame
to visible much before you actually added all components to it, and make it realize its size.Absolute Layout
, which one should avoid in most of the situations.Graphics
object explicitly, which one should avoid and instead use the one provided by Java's paintComponent ( ... )
method by defaultHave a look at this example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DrawingCircleExample {
private JPanel drawingBoard;
private JButton button;
private static final int GAP = 5;
private void displayGUI () {
JFrame frame = new JFrame ( "" );
frame.setDefaultCloseOperation ( JFrame.DISPOSE_ON_CLOSE );
JPanel contentPane = new JPanel ();
contentPane.setLayout ( new BorderLayout ( GAP, GAP ) );
drawingBoard = new DrawingBoard ();
contentPane.add ( drawingBoard, BorderLayout.CENTER );
button = new JButton ( "Draw" );
button.addActionListener ( new ActionListener () {
@Override
public void actionPerformed ( ActionEvent ae ) {
DrawingBoard board = ( DrawingBoard ) drawingBoard;
board.setState ();
}
} );
contentPane.add ( button, BorderLayout.PAGE_END );
frame.setContentPane ( contentPane );
frame.pack ();
frame.setLocationByPlatform ( true );
frame.setVisible ( true );
}
public static void main ( String [] args ) {
Runnable runnable = new Runnable () {
@Override
public void run () {
new DrawingCircleExample ().displayGUI ();
}
};
EventQueue.invokeLater ( runnable );
}
}
class DrawingBoard extends JPanel {
private static final int TOTAL_RECTANGLES = 5;
private static final int WIDTH = 400;
private static final int HEIGHT = 300;
private static final int RADIUS = 50;
private static final int X = 50;
private static final int Y = 50;
private int counter;
private int moveXBy;
private boolean isActive;
private int count;
public DrawingBoard () {
setOpaque ( true );
counter = 0;
count = 0;
isActive = false;
moveXBy = ( RADIUS + ( counter ) * RADIUS );
}
public boolean setState () {
isActive = true;
System.out.println ( "Outside MoveXBy: " + moveXBy );
++counter;
counter %= TOTAL_RECTANGLES;
int x = ( RADIUS + ( counter ) * RADIUS );
if ( moveXBy != x ) {
System.out.println ( "Inside First MoveXBy: " + moveXBy );
repaint ( moveXBy, RADIUS, X, Y );
moveXBy = x;
System.out.println ( "Inside Second MoveXBy: " + moveXBy );
repaint ( moveXBy, RADIUS, X, Y );
}
return isActive;
}
@Override
public Dimension getPreferredSize () {
return new Dimension ( WIDTH, HEIGHT );
}
@Override
protected void paintComponent ( Graphics g ) {
super.paintComponent ( g );
g.drawRect ( 50, RADIUS, X, Y );
g.drawRect ( 100, RADIUS, X, Y );
g.drawRect ( 150, RADIUS, X, Y );
g.drawRect ( 200, RADIUS, X, Y );
g.drawRect ( 250, RADIUS, X, Y );
g.setColor ( Color.RED );
g.fillOval ( moveXBy, RADIUS, X, Y ) ;
}
}
EDIT regarding comment:
All Graphical User Interfaces require some kind of main application frame in which to display. In Swing, this is an instance of javax.swing.JFrame
. Therefore, our first step is to instantiate this class and make sure that everything works as expected. Note that when programming in Swing, your GUI creation code should be placed on the Event Dispatch Thread (EDT), more info on Concurrency in Swing. This will prevent potential race conditions that could lead to deadlock.
DrawingBoard
also overrides getPreferredSize, which returns the desired width and height of the panel (in this case 400
is the width
, 300
is the height.) Because of this, the DrawingCircleExample
class no longer needs to specify the size of the frame in pixels. It simply adds the panel to the frame and then invokes pack.
The paintComponent
method is where all of your custom painting takes place. This method is defined by javax.swing.JComponent
and then overridden by your subclasses to provide their custom behavior. Its sole parameter, a java.awt.Graphics object, exposes a number of methods for drawing 2D shapes and obtaining information about the application's graphics environment. In most cases the object that is actually received by this method will be an instance of java.awt.Graphics2D (a Graphics subclass), which provides support for sophisticated 2D graphics rendering.
Most of the standard Swing components have their look and feel implemented by separate "UI Delegate" objects. The invocation of super.paintComponent(g) passes the graphics context off to the component's UI delegate, which paints the panel's background.
To keep our custom painting as efficient as possible, we will track the X coordinates ( moveXBy
variable in our case ) and repaint only the areas of the screen that have changed. This is a recommended best practice that will keep your application running as efficiently as possible.
The invocation of the repaint
method. This method is defined by java.awt.Component
and is the mechanism that allows you to programatically repaint the surface of any given component. It has a no-arg version (which repaints the entire component) and a multi-arg version (which repaints only the specified area.) This area is also known as the clip. Invoking the multi-arg version of repaint takes a little extra effort, but guarantees that your painting code will not waste cycles repainting areas of the screen that have not changed.
Because we are manually setting the clip, our setState
method invokes the repaint
method not once, but twice. The first invocation tells Swing to repaint the area of the component where the oval previously was (the inherited behavior uses the UI Delegate to fill that area with the current background color.) The second invocation paints the area of the component where the oval currently is. An important point worth noting is that although we have invoked repaint
twice in a row in the same event handler, Swing is smart enough to take that information and repaint those sections of the screen all in one single paint operation. In other words, Swing will not repaint the component twice in a row, even if that is what the code appears to be doing.
Refer further on the topic at performing Custom Painting