I have two classes below: And I'm trying to make it so that calling FilledFrame would make certain shapes. I've tested it with a Line below, but it doesn't show up on the GUI. Is there something I'm doing wrong here? I also need to make a Card class that is able to modify some rectangle's positions, so would I need to make a graphics object in the main and enter it into FilledFrame and my Card class?
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import javax.swing.*;
public class FilledFrame extends JFrame implements ActionListener {
static int FRAME_WIDTH = 500;
static int FRAME_HEIGHT = 100;
Graphics g = getGraphics();
public FilledFrame () {
g.drawLine(1, 1, 100, 100);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setVisible(true);
}
private void createComponents() {
...
}
private void createCards() {
...
}
#Override
public void actionPerformed(ActionEvent e) {
}
public static void draw (Graphics g) {
g.fillRect(0, 50, 100, 150);
}
}
Main class:
import java.awt.Graphics;
import java.awt.Shape;
import java.awt.geom.Line2D;
import java.awt.geom.Line2D.Float;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.Canvas;
import javax.swing.JComponent;
import javax.swing.JPanel;
public class Main {
public static void main (String args[]) {
FilledFrame frame = new FilledFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.show();
}
}
Is there something I'm doing wrong here?
Sorry to say, but you're guessing at how to do Swing drawing, and while this might work with simple Java concepts, it won't for something as complex as Swing graphics.
Problems include:
Trying to draw directly within the JFrame -- never do this, but instead draw in a JPanel.
Calling getGraphics() on a component to get a Graphics resource. This will lead to your getting an unstable and short-lived Graphics object that can lead to either failed painting or NullPointerExceptions
Not drawing in an appropriate painting method.
You're using int literals in your drawing method parameters rather than int variables, making any drawing that you do do, fixed -- you can never move or change it.
Instead I suggest that you:
Create a class that extends JPanel and paint in that class.
Draw within this class's protected void paintComponent(Graphics g) method.
Don't forget to call the super's paintComponent method within your override so that your GUI cleans up any dirty pixels.
Then place that JPanel into the JFrame that needs to display it.
Use int fields (variables) not int literals (so-called "magic" numbers) for most of your drawing method parameters so that your drawings can change if you so desire while the program runs.
And most important, read and study the standard Swing graphics tutorials.
Resources:
The Really Big Index: the main tutorial where you should start.
Using Swing Components: how to create Swing GUI's
Lesson: Performing Custom Painting: introductory tutorial to Swing graphics
Painting in AWT and Swing: advanced tutorial on Swing graphics
Related
I am starting to learn how to make graphics in Java. But if I draw something in my Frame and I run the program. those parts of the Frame where I did not draw anything there is the picture of the Frame running behind my Program. hw can I avoid this?
package de.sarah;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
public class Framemg extends JFrame{
public Framemg() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("Zeichnen mit Java");
setSize(400, 300);
setBackground(Color.yellow);
setVisible(true);
}
public void paint(Graphics g) {
g.drawString( "Hellooo", 120, 60 );
}
}
package de.sarah;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Insets;
public class Main{
public static void main(String[] args) {
Framemg Frame = new Framemg();
}
}
Don't override paint() of a JFrame.
Custom painting is done by overriding the paintComponent(...) method of a JPanel. Then you add the panel to the frame.
Read the section from the Swing tutorial on Custom Painting for more information and working examples to get you started.
This code won't fill the rectangle. I tried to extend JComponent but I received an error. How would I extend JComponent?
package com.lewis.GooseEgg;
import java.awt.*;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class GooseEgg extends Canvas{ //I couldn't extend JComponent
//How would I also extend JComponent
protected void paintComponent(Graphics g){
g.setColor(Color.BLACK);
g.fillRect(0,0, 100, 100);
}
public static void main(String[] args) {
//This is just all the basic stuff I learned
JFrame frame = new JFrame();
GooseEgg goose = new GooseEgg();
frame.setResizable(false);
frame.setTitle("Goose Egg");
frame.add(goose);
frame.pack();
frame.setSize(900, 900);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//The website keeps asking me to add more detail because it says my post is mostly code so I added this. If anyone wants to tutor me at Java
//I could pay money.
}
}
You don't need to extend from Canvas and JComponent: You should only extend from JComponent.
Also you should not do pack() and setSize(…). They both set the size of your frame, this does not make sense. Either do pack() (in which case you also need to specify a preferred size e.g. by overriding getPreferredSize() or setting it with setPreferredSize(…)) or do setSize(…).
Changing Canvas to JComponent and removing the pack() method call seems to produce the correct result.
Ok, I have been workinng of mending this for the past hour or more. I wanted to seperate the player class and the applet being drawn for convience when I add more to the player class it will be more organized. But, since I did this I have had error after error and I have another file similiar to this one where it draws the applet in the same file with no errors and runs. I have looked at it step by step and still can not find it. So I was hoping somebody could explain why I am getting these three errors.
player.java
package com.powder.game;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class player implements KeyListener{
private Rectangle rect;
public void init(){
rect = new Rectangle(10, 10, 50, 50); // make the rectangle
this.addKeyListener(this); // Listens to see if Rectangle is pressed
}
public void paint(Graphics e){
super.paint(e);
Graphics2D g2 = (Graphics2D) e;
g2.setColor(Color.RED); // Sets a color for the rectangle
g2.fill(rect);
}
public void keyTyped(KeyEvent e){
}
#Override
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_E){
rect.setLocation(rect.x, rect.y-10);
}
if(e.getKeyCode() == KeyEvent.VK_S){
rect.setLocation(rect.x-10, rect.y);
}
if(e.getKeyCode() == KeyEvent.VK_D){
rect.setLocation(rect.x, rect.y+10);
}
if(e.getKeyCode() == KeyEvent.VK_F){
rect.setLocation(rect.x+10, rect.y);
}
repaint();
}
public void KeyReleased(KeyEvent e){
}
}
MyFrameInit.java
package com.powder.game;
import javax.swing.*;
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.io.IOException;
import java.lang.Math;
import javax.swing.ImageIcon;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import com.powder.game.player;
public class MyFrameInit extends Applet {
player p = new player();
public void paint(Graphics g){
super.paint(g); // Super calls the parent
g.setColor(Color.BLUE); // Setting color for g (background)
g.fillRect(0, 0, 600, 400); // fill the background blue at x,y,width,height
this.setSize(600, 400); // Set the size of the applet
p.init();
}
}
Sorry if the formatting for the page isn't right. Still trying to understand this. I'm so used to tags lol.
EDIT: So, I extended Applet to player and it fixed almost everything I just added
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
that to the end and it started to work. Now my only problem is it's not keeping MyFrameInit.java when after I go to init() in player.java how could I fix this?
Problems
Player does not have methods...
addKeyListener
repaint
It does not inherit from anything, therefore it can't call...
super.paint, as it's parent classes do not have this method...
You can't call what you don't have...
Player does not meet to contractual requirements of the KeyListener interface, it does not implement
public void keyReleased(KeyEvent e)
Painting is for painting the current state of the component, you should never modify the state of the component or any child components from within any paint method, as this can produce an infinite loop of repaints
Don't do:
this.setSize(600, 400); // Set the size of the applet - You should never try and set the size of an applet, the size is determined by the HTML tag
p.init();. Your paint method will be called a lot of times over the life cycle of your program, it's pointless to initialise objects within that require there state to be maintained between calls
Recommendations
Start by using a JApplet instead of an Applet
Extending your Player from a JPanel; override it's paintComponent method instead of it's paint method (calling super.paintComponent instead); override it's getPreferredSize method and return a reasonable default size for the component
add Player to the JApplet...
Use the key bindings API instead of KeyListener, see How to Use Key Bindings. This will save you a few more days of head scratching and frustration.
I have a animation class which simply draws two circles and a line (no main method), in another class i have a main method which is passed the animation class as a object and should show the two circles that I have drawn but it doesn't show, it only shows the window none of the circles or the line that I have done, if i was to put the main method in my animation class it will work perfectly, this is a user error somehow but I'm not sure what or why.
The animation method in separate class.
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.Graphics.*;
import javax.swing.JApplet;
public class Animation extends JApplet{
public void init(){
}
public static void createAndShowGUI(JApplet j)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
frame.setSize(500,500);
frame.getContentPane().add("Center", j);
}
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D) g;
int x=50;
int y=10;
g2.setPaint(Color.black);
g2.draw(new Line2D.Double(x,y,50,400));
drawT(g2);
drawH(g2);
//create a method that translates
}
public void drawH(Graphics2D g2)
{
int y=25;
g2.setColor(Color.blue);
drawCircle(y,g2);
}
public void drawT(Graphics2D g2){
int y=100;
g2.setColor(Color.green);
drawCircle(y,g2);
}/*
public void raceLoop(){
long startingTime = System.currentTimeMillis();
long cumTime=startingTime;
while(mve.hposition<70){
long timePassed = System.currentTimeMillis()-cumTime;
cumTime += timePassed;
//mve.update(timePassed);
}
}*/
public void drawCircle(int y, Graphics2D g2)
{
g2.fillOval(50,y,50,50);
}
}
The Main Method
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.Graphics.*;
import javax.swing.JApplet;
public class Race {
public static void main(String[] args) {
JApplet applet = new JApplet();
Animation animie = new Animation();
animie.createAndShowGUI(applet);
}
}
You don't need to (or want) extend from JApplet if all you're going to is use a JFrame. You're better of (in any case), extending from JPanel (as this can then be added to a JApplet or JFrame)
You've not added anything to the JFrame, so, in fact, you program is doing exactly what you told it to.
You should very rarely need to override the paint method of a top level container (like JApplet or JFrame), instead, use JPanel and override it's paintComponent method.
You should always call super.paintXxx, the paint methods chain together to paint the various aspects of the application and it will end in tears if you break this chain.
You might like to have a read through
Creating a GUI With JFC/Swing
Performing Custom Painting
Painting in AWT and Swing
For some more background
Looks like you're passing the wrong reference to the createAndShowGui(..) method.
Try this on your Race class:
import javax.swing.*;
import java.awt.geom.*;
import java.awt.*;
import java.awt.Graphics.*;
import javax.swing.JApplet;
public class Race {
public static void main(String[] args) {
Animation animie = new Animation();
animie.createAndShowGUI(animie);
}
}
I have created an application which requires the reloading of an image several times throughout the program execution. Perhaps it's clumsy, but my implementation was to extend the Component class in a subclass and reload the image via a fileName argument to it's constructor. The code is included below:
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.WindowConstants;
public class Grapher {
private static JFrame frame = new JFrame("Test Frame");
private static Graph graph = null;
private static JScrollPane jsp = null;
public Grapher(){
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
public void display(String fileName) {
if(jsp != null)
frame.getContentPane().remove(jsp);
graph = new Graph(fileName);
jsp = new JScrollPane(graph);
frame.getContentPane().add(jsp);
frame.setSize(graph.getPreferredSize());
frame.setVisible(true);
}
private class Graph extends Component{
BufferedImage img;
#Override
public void paint(Graphics g) {
g.drawImage(img, 0, 0, null);
}
public Graph(String fileName) {
setFocusable(false);
try {
img = ImageIO.read(new File(fileName));
} catch (IOException e) {System.err.println("Error reading " + fileName);e.printStackTrace();}
}
}
}
Anyway, my problem is that whenever I call the display command this window steals the focus of everything java, including eclipse, which can be really agravating. I even tried adding setFocusable(false) in the constructor, but it still manages to steal the focus. How do I tell it to be focusable but not focus automatically with construction?
Perhaps it's clumsy, but my implementation was to extend the Component class in a subclass and reload the image via a fileName argument to it's constructor
There is no need for a custom component. Just use a JLabel and the setIcon(...) method when you want to change the image.
Even if you did need a custom component you would not extend Component, you would extend JComponent or JPanel in a Swing application.
Setting a frame visible automatically gives the frame focus. You can try using:
frame.setWindowFocusableState( false );
Then you might need to add a WindowListener to the frame. When the window is opened you can reset the focusable state to true.