I am trying to figure out how to repaint() a class that extends the JComponent. I want to have each class extend JComponent and then supply its own paintComponent(). (super.paintComponent(). This way I can make a circle class or whatever class that I want to make and then I can repaint() it when ever I want to as long as it is added to the JPanel that goes in the JFrame. Below are all of the code that are needed to run.
Class 1:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
public class DDHGenericFrame extends JFrame {
private static final long serialVersionUID = 1L;
/* User defined class that is below */
DDHGenericPanel d = new DDHGenericPanel();
public DDHGenericFrame() {
initUI();
}
public final void initUI() {
add(d);
setSize(650, 350);
setTitle("Lines");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
DDHGenericFrame ex = new DDHGenericFrame();
ex.setVisible(true);
}
}
Class 2:
import java.awt.Graphics;
import javax.swing.JPanel;
class DDHGenericPanel extends JPanel {
private static final long serialVersionUID = 1L;
DDHGenericPanel() {
System.out.println("DDH Generic JPanel");
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//paint code goes here of whatever
}
}
Class 3:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
public class DDHCircleOne extends JComponent {
private static final long serialVersionUID = 1L;
int counter = 0;
public DDHCircleOne() {
counter++;
System.out.println("DDHCircle Constructor");
}
public void paintComponent(Graphics g2) {
super.paintComponent(g2);
Graphics2D c2D = (Graphics2D) g2;
c2D.setColor(Color.yellow);
c2D.fillRect(0, 0, getSize().width, getSize().height);
if (counter % 2 == 2) {
System.out.println("RED");
counter++;
c2D.setColor(Color.red);
c2D.fillRect(0, 0, getSize().width, getSize().height);
} else {
System.out.println("BLUE");
counter++;
c2D.setColor(Color.blue);
c2D.fillRect(0, 0, getSize().width, getSize().height);
}
}
}
The above three classes are what I have in my package. I want DDHCircleOne to be able to repaint it self whenever an instance of it is created and calls the method repaint(). This way I can just make a class that extends JComponent and then override the paintComponent() and then call repaint().
If I had a button that said repaint in red and another button that says repaint in blue the circle or whatever I had in the frame will repaint itself when the variableName.repaint() is called.
doughauf#outlook.com
public void paintComponent(Graphics g) {
super.paintComponent(g);
repaint();
}
Never invoke repaint() in a painting method. This will cause an infinite loop.
There is no need for you generic panel. You can add a component to any panel.
If you want the color of the circle to change, then you need to change a property of your component. For example you can just use the setForeground(...) method to change the color:
//c2D.setColor(Color.red);
c2D.setColor( getForeground() );
So when you click on your button you just invoke circle.setForeground(Color.RED);
The setForeground() method of JComponent will invoke the repaint() method on the component for you.
Related
I've been trying tp paint an image of a cheetah just to mess around with the paint method and such, but it doesn't seem to be working, any idea why?
I've tried a ton of stuff i found on here but nothing seems toi work at all, all i get is my button, i know its the actual paint method not working because it doesn't even pain the Hello string.
Here's the main class:
package dev.main;
import javax.swing.JFrame;
import javax.swing.JPanel;
import dev.angora.gui.GameGUI;
#SuppressWarnings("serial")
public class Main extends JFrame {
public static JFrame p = new JFrame("Angora Realms");
public static void main (String[] args) {
new Main();
}
public Main() {
p.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p.pack();
p.setSize(640, 800);
p.setVisible(true);
p.setLayout(null);
GameGUI g = new GameGUI();
g.createGui(p);
}
}
And here is the class I try to paint in:
package dev.gui;
import java.awt.Button;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GameGUI extends JFrame implements ActionListener {
public Button drawCard = new Button("Draw Card");
public Image cheetah = null;
public void createGui(JFrame p) {
drawCard.addActionListener(this);
drawCard.setBounds(20,30,80,30);
p.add(drawCard);
}
#Override
public void actionPerformed(ActionEvent event) {
Object cause = event.getSource();
if (cause == drawCard) {
System.out.println("Ay");
}
}
public void paintComponent(Graphics g) {
super.paint(g);
g.drawString("Hello", 200, 50);
if (cheetah == null) {
cheetah = getImage("plains/Cheetah.png");
Graphics2D g2 = (Graphics2D)g;
g2.drawImage(cheetah, 100, 100, 100, 300, this);
}
}
public Image getImage(String path) {
Image tempImage = null;
try {
URL imageURL = GameGUI.class.getResource(path);
tempImage = Toolkit.getDefaultToolkit().getImage(imageURL);
}
catch (Exception e) {
System.out.println("An error occured -" + e.getMessage());
}
return tempImage;
}
} '
You're creating something like three JFrames, so it's kind of hard to track where things are actually going. There is no need to use extends JFrame for either of the two classes you presented, in fact, this will highlight the cause of your error...
JFrame does not have a paintComponent method, so it will never be called, instead, change GameGUI to extend from JPanel and add #Override to the start of the paintComponent method declaration (before it), then change super.paint(g); to super.paintComponent(g);
For example...
public class GameGUI extends JPanel implements ActionListener {
public Button drawCard = new Button("Draw Card");
public Image cheetah = null;
public void createGui(JFrame p) {
drawCard.addActionListener(this);
drawCard.setBounds(20,30,80,30);
p.add(drawCard);
}
#Override
public void actionPerformed(ActionEvent event) {
Object cause = event.getSource();
if (cause == drawCard) {
System.out.println("Ay");
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
No offense, but I'm not a fan of passing a reference of the "container" to the child component so it can add itself in this way. Better to create an instance of GameGUI and add it to what ever container you want. The GameGUI doesn't need to know or care...IMHO
Runnable Example
Don't use pack and setSize, they are competing with each other. The content of the frame should dictate the size of the frame. This is done through the use of appropriate layout managers and overriding getPreferredSize of custom components.
Don't call setVisible until AFTER you've established the base UI
Make sure you are adding your components to a displayable surface if you expect them to be painted
Also, you're mixing heavy weight (java.awt.Button) and light weight (Swing/javax.swing.JFrame) components together...my recommendation is, don't, this will cause a bunch of other issues you really don't need to deal with.
import java.awt.Button;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JFrame {
public static void main(String[] args) {
new Main();
}
public Main() {
JFrame p = new JFrame("Angora Realms");
p.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GameGUI g = new GameGUI();
p.add(g);
p.setSize(640, 800);
p.setVisible(true);
}
public class GameGUI extends JPanel implements ActionListener {
public Button drawCard = new Button("Draw Card");
public Image cheetah = null;
public GameGUI() {
drawCard.addActionListener(this);
add(drawCard);
}
#Override
public void actionPerformed(ActionEvent event) {
Object cause = event.getSource();
if (cause == drawCard) {
System.out.println("Ay");
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawString("Hello", 200, 50);
if (cheetah == null) {
cheetah = getImage("plains/Cheetah.png");
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(cheetah, 100, 100, 100, 300, this);
}
}
public Image getImage(String path) {
Image tempImage = null;
try {
URL imageURL = GameGUI.class.getResource(path);
tempImage = Toolkit.getDefaultToolkit().getImage(imageURL);
} catch (Exception e) {
System.out.println("An error occured -" + e.getMessage());
}
return tempImage;
}
}
}
I've made a JFrame, and added a JPanel to it. I am trying to paint the window completely black, and it isn't working! Thank you in advance.
This is my Main class!
package com.lootdatdungeon.net;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args){
initWindow();
}
public static void initWindow(){
Window window = new Window();
Thread windowThread = new Thread(window);
windowThread.start();
}
}
Okay, and here is my Window class!
package com.lootdatdungeon.net;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Window extends JFrame implements Runnable{
private static final long serialVersionUID = 1L;
private static final int HEIGHT = 240;
private static final int WIDTH = 320;
private static final int SCALE = 2;
private BufferedImage image;
private Graphics2D g;
private boolean running = true;
public Window(){
System.out.println("Window object made");
JFrame frame = new JFrame("Loot dat dungeon");
JPanel panel = new JPanel();
frame.setSize(WIDTH*SCALE,HEIGHT*SCALE);
frame.setVisible(true);
frame.setResizable(false);
frame.add(panel);
image = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
}
public void Draw(Graphics g){
System.out.println("Draw method ran");
g.setColor(Color.BLACK);
g.drawRect(0, 0, WIDTH, HEIGHT);
}
#Override
public void run() {
while(running){
Draw(g);
}
}
}
Simply do in this way using overriiden paintComponent() method of JPanel
JPanel panel = new JPanel() {
#Override
public void paintComponent(Graphics g) {
// don't forget to call it
super.paintComponent(g);
// set color
g.setColor(Color.BLACK);
// fill a rect that cover whole panel with specified color
g.fillRect(0, 0, getWidth(), getHeight());
}
};
Note: There is no need of Thread and BufferedImage in this case.
You should give this a read http://www.gametutorial.net/article/Java-game-framework
That site has a lot of good info if you want to create games. That's there I started.
I'm wondering if any of you know how to display a nice looking progress bar in Java, mostly using Swing, although I don't mind using third-party libraries.
I've been looking at JProgressBar tutorials but none of them refer to styling the bar. Reading the API I found a getUI method that returns ProgressBarUI object but I don't see many ways to customize that one.
What I want is to add rounded corners, change background and foreground color, width, lenght, the usual.
Thanks!
If you don't want to replace the user's chosen Look & Feel, you can just replace the UI delegate with one derived from BasicProgressBarUI.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.plaf.basic.BasicProgressBarUI;
/** #see http://stackoverflow.com/questions/8884297 */
public class ProgressBarUITest extends JPanel {
public ProgressBarUITest() {
JProgressBar jpb = new JProgressBar();
jpb.setUI(new MyProgressUI());
jpb.setForeground(Color.blue);
jpb.setIndeterminate(true);
this.add(jpb);
}
private static class MyProgressUI extends BasicProgressBarUI {
private Rectangle r = new Rectangle();
#Override
protected void paintIndeterminate(Graphics g, JComponent c) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
r = getBox(r);
g.setColor(progressBar.getForeground());
g.fillOval(r.x, r.y, r.width, r.height);
}
}
private void display() {
JFrame f = new JFrame("ProgressBarUITest");
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 ProgressBarUITest().display();
}
});
}
}
The easiest way to do that would be to change the LookAndFeel or maybe even create your own class that extends off of one of the default L&Fs and just changes the UI for the progress bar...
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 want to make an image that I drew in the paint class move left across my JFrame as a timer ticks. But I don't know how to do that. Also, I am trying to get my program to make the image disappear when the image is clicked upon.
movingball class
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JPanel;
import javax.swing.Timer;
public class movingball extends JPanel{
private int move=50;
private Timer timer = new Timer(move, new TimerListener());
private int radius = 10;
private int x = 300;
private int y = 0;
public movingball() {
timer.start();
}
private class TimerListener implements ActionListener{
public void actionPerformed(ActionEvent e){
x=x-20;
repaint(); }//trying to get the oval to move left 20
}
protected void paintComponent(Graphics2D g){
super.paintComponent(g);
g.fillOval(x, 100 , radius * 2, radius * 2); }
}
movingControl class
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
public class movingControl extends JPanel {
private movingball ball= new movingball();
public movingControl(){
JPanel panel = new JPanel();
ball.setBorder(new javax.swing.border.LineBorder(Color.red));
panel.addMouseListener(new movingballListener());
setLayout(new BorderLayout());
add(ball, BorderLayout.CENTER);
add(panel, BorderLayout.SOUTH);
}
}
SnniperGameApp class
I know I spelled sniper wrong
import javax.swing.JApplet;
public class SnniperGameApp extends JApplet {
static final long serialVersionUID = 2777718668465204446L;
//i dont know what this serial thing is. But my program wont start without it
public SnniperGameApp(){
add(new movingControl());
}
}
ClickingEvent class
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
class movingballListener extends MouseAdapter{
public void mouseReleased(MouseEvent e) {
if ((e.getModifiers() & InputEvent.BUTTON1_DOWN_MASK) != 0) {
System.out.println( (e.getPoint()));}}
}
You haven't over-ridden paintComponent() properly.
From the javadoc, the signature of paintComponent() is:
protected void paintComponent(Graphics g)
but you have:
protected void paintComponent(Graphics2D g)
The method signatures must match - you can safely cast the Graphics to a Graphics2D inside the method if needed.
Adding the #Override annotation to a method is a good way to get the compiler to check that you really are over-riding a method, not just writing a method that looks the same!
Here's a working SSCCE (I have inlined some of the constants to save space, don't take that as good practice for real code!):
public class MovingBall extends JPanel
{
private Timer timer = new Timer(50, new TimerListener());
private int x = 300;
public MovingBall()
{
timer.start();
}
private class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
x -= 20;
repaint();
}
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillOval(x, 100, 20, 20);
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.add(new MovingBall());
frame.setSize(500, 500);
frame.setVisible(true);
}
}