I am trying to display a timer count, but it is not being displayed, but everything else works fine. Thank you for helping btw.
import javax.swing.*;
import java.util.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Tester {
static Timer timer;
static JFrame frame;
static JPanel panel;
public static void init(){
frame = new JFrame();
panel = new JPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500, 500);
frame.add(panel);
}
The method above is just to make code cleaner.
public static void main(String[] args) {
init();
class Clicker extends JPanel{
int timesClicked;
public Clicker(){
timesClicked = 0;
}
void updateClicks(){
timesClicked++;
repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
System.out.println("Called!!!");
g2.drawString("Half Seconds: "+timesClicked, 100, 100);
}
} //end of Clicker
drawString method not working is above.
final Clicker c = new Clicker();
panel.add(c);
class TimeChecker implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked!");
c.updateClicks();
}
}// end of TimeChecker
ActionListener listener = new TimeChecker();
timer = new Timer(500,listener);
timer.start();
}
}
You have a combination of issues
Clicker was never actually added to anything
panel uses a FlowLayout by default, but Clicker provides no sizing hints, so it's sized to 0x0
You code generally is setup a little weird. I would learn to do without static very, very quickly.
Quick and fast solution...
Change the layout manager for panel to BorderLayout...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Test {
static Timer timer;
static JFrame frame;
static JPanel panel;
public static void init() {
frame = new JFrame();
panel = new JPanel(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500, 500);
frame.add(panel);
}
public static void main(String[] args) {
init();
class Clicker extends JPanel {
int timesClicked;
public Clicker() {
timesClicked = 0;
}
void updateClicks() {
timesClicked++;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
System.out.println("Called!!!");
g2.setColor(Color.BLACK);
g2.drawString("Half Seconds: " + timesClicked, 100, 100);
}
} //end of Clicker
final Clicker c = new Clicker();
panel.add(c);
panel.revalidate();
panel.repaint();
class TimeChecker implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked!");
c.updateClicks();
}
}// end of TimeChecker
ActionListener listener = new TimeChecker();
timer = new Timer(500, listener);
timer.start();
}
}
A slightly different approach (with out static)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Clicker clicker = new Clicker();
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(clicker);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
class TimeChecker implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked!");
clicker.updateClicks();
}
}// end of TimeChecker
ActionListener listener = new TimeChecker();
Timer timer = new Timer(500, listener);
timer.start();
}
});
}
public class Clicker extends JPanel {
private int timesClicked;
public Clicker() {
timesClicked = 0;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 200);
}
void updateClicks() {
timesClicked++;
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
System.out.println("Called!!!");
g2.setColor(Color.BLACK);
g2.drawString("Half Seconds: " + timesClicked, 100, 100);
}
}
}
Related
To be more specific I edit the question by replacing it with some reproducible code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class TestStackOverflow {
public static void main(String[] args) {
new TestStackOverflow();
}
public TestStackOverflow() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame window = new JFrame();
window.setSize(new Dimension(1000, 1000));
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel header = new JPanel();
header.add(new JLabel("Hello, I'm the header"));
header.setBackground(Color.red);
window.add(header, BorderLayout.NORTH);
window.add(new TestPane());
window.setLocationRelativeTo(null);
window.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBackground(Color.blue);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(900, 0, 100, 100);
//System.out.println(getWidth());
}
}
}
This code shows the rectangle being drawn too far right. I saw with "getWidth" that the width is actually less then 1000, but I had defined with window.setSize(new Dimension(1000, 1000)) the size of the window. So, why is it just 984 instead of 1000. The swing documentation says that the component would take the remaining space and that would / should be in my case 1000.
image of wrong placed rectangle
You seem to want it in the corner of the whole window. In that case you need to override the frame's painting method. Demo obviously - I'm not suggesting you write it exactly like this:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class TestStackOverflow {
public static void main(String[] args) {
new TestStackOverflow();
}
public TestStackOverflow() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame window = new JFrame() {
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawRect(900, 0, 100, 100);
// System.out.println(getWidth());
}
};
window.setSize(new Dimension(1000, 1000));
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel header = new JPanel();
header.add(new JLabel("Hello, I'm the header"));
header.setBackground(Color.red);
window.add(header, BorderLayout.NORTH);
window.add(new TestPane());
window.setLocationRelativeTo(null);
window.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBackground(Color.blue);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//g.drawRect(900, 0, 100, 100);
// System.out.println(getWidth());
}
}
}
Am trying to change color after drawing the object in window, this is what i came up with, am a beginner so this is messy.
import java.awt.*;
import java.awt.event.*;
import java.awt.event.WindowEvent;
import java.util.Arrays;
import java.util.List;
public class TestGraphic extends Figure {
TestGraphic(){
setSize(600,600);
closeFrame();
}
public static void main(String[] args) {
TestGraphic test = new TestGraphic();
test.setVisible(true);
}
public void paint(Graphics gui) {
drawComponent(gui);
}
public void drawComponent(Graphics gui) {
gui.drawOval(108,110,200,200);
gui.drawOval(160,150,20,20);
gui.drawOval(240,150,20,20);
gui.drawRect(160,220,100,40);
Button btn = new Button("Change color");
btn.setBounds(30,100,80,30);
add(btn);
changeColor(gui,btn);
}
#Override
void draw(Graphics gui) {
// TODO Auto-generated method stub
}
#Override
public boolean contains(int x, int y) {
return false;
}
private void closeFrame(){
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
System.exit(0);
}
});
}
void changeColor(Graphics gui,Button btn) {
List<Color> colorList;
colorList = Arrays.asList(Color.black, Color.blue , Color.cyan, Color.red, Color.green, Color.magenta, Color.orange, Color.yellow);
btn.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent e) {
for(int i = 0;i < colorList.size(); i++) {
gui.setColor(colorList.get(i));
}
}
});
}
}
The class Figure is an abstract class that is inheriting from java.awt.Frame
Any remarks about how to make this code cleaner will be appreciated, thanks.
Before you begin on something as complex as custom painting, make sure you have a firm understanding of the basics of the language and the APIs
See Creating a GUI With Swing, Performing Custom Painting and Painting in AWT and Swing for more details.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Color desiredColor = Color.BLACK;
private List<Color> avaliableColors = new ArrayList<>(16);
public TestPane() {
setLayout(new BorderLayout());
avaliableColors.add(Color.BLACK);
avaliableColors.add(Color.BLUE);
avaliableColors.add(Color.CYAN);
avaliableColors.add(Color.DARK_GRAY);
avaliableColors.add(Color.GRAY);
avaliableColors.add(Color.GREEN);
avaliableColors.add(Color.LIGHT_GRAY);
avaliableColors.add(Color.MAGENTA);
avaliableColors.add(Color.ORANGE);
avaliableColors.add(Color.PINK);
avaliableColors.add(Color.RED);
avaliableColors.add(Color.WHITE);
avaliableColors.add(Color.YELLOW);
JButton btn = new JButton("Change color");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Randomise the colors
Collections.shuffle(avaliableColors);
desiredColor = avaliableColors.get(0);
repaint();
}
});
add(btn, BorderLayout.SOUTH);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(desiredColor);
g2d.drawOval(108, 110, 200, 200);
g2d.drawOval(160, 150, 20, 20);
g2d.drawOval(240, 150, 20, 20);
g2d.drawRect(160, 220, 100, 40);
g2d.dispose();
}
}
}
Since you're just starting out, I might suggest getting started with JavaFX instead
AWT
!! Warning !!
No one uses AWT anymore and you're not likely to get much in the way of support for it here. This is a "basic" concept converted from the previous example, beware, AWT isn't double buffered by default
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JButton;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Frame frame = new Frame();
frame.add(new TestCanvas());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestCanvas extends Container {
private Color desiredColor = Color.BLACK;
private List<Color> avaliableColors = new ArrayList<>(16);
public TestCanvas() {
setLayout(new BorderLayout());
avaliableColors.add(Color.BLACK);
avaliableColors.add(Color.BLUE);
avaliableColors.add(Color.CYAN);
avaliableColors.add(Color.DARK_GRAY);
avaliableColors.add(Color.GRAY);
avaliableColors.add(Color.GREEN);
avaliableColors.add(Color.LIGHT_GRAY);
avaliableColors.add(Color.MAGENTA);
avaliableColors.add(Color.ORANGE);
avaliableColors.add(Color.PINK);
avaliableColors.add(Color.RED);
avaliableColors.add(Color.WHITE);
avaliableColors.add(Color.YELLOW);
JButton btn = new JButton("Change color");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Randomise the colors
Collections.shuffle(avaliableColors);
desiredColor = avaliableColors.get(0);
repaint();
}
});
add(btn, BorderLayout.SOUTH);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(desiredColor);
g2d.drawOval(108, 110, 200, 200);
g2d.drawOval(160, 150, 20, 20);
g2d.drawOval(240, 150, 20, 20);
g2d.drawRect(160, 220, 100, 40);
g2d.dispose();
}
}
}
I have a button. I want to change the background after I click on it. My problem here is the button auto call paintComponent(). How can prevent this? I expect after clicking the button the button will be blue, but it will still be red.
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ButtonDemo extends JButton implements ActionListener{
public ButtonDemo() {
this.setText("BUTTON TEXT");
this.addActionListener(this);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.RED);
}
public static void main(String[] args){
JFrame frame = new JFrame();
JPanel contentPane = new JPanel();
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo());
frame.setSize(500, 500);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
this.setBackground(Color.BLUE);
}
}
My personal gut feeling is that JButton is probably not suited to your desired goal.
Essentially, you want to control when and how the "selected" state of the piece is changed.
Personally, I would have some kind of controller which monitored the mouse events in some way (probably having the piece component delegate the event back to the controller) and some kind of model which control when pieces become selected, this would then notify the controller of the state change and it would make appropriate updates to the UI.
But that's a long process to setup. Instead, I'm demonstrating a simple concept where a component can be selected with the mouse, but only the controller can de-select. In this example, this will allow only a single piece to be selected
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(5, 5));
ChangeListener listener = new ChangeListener() {
private PiecePane selectedPiece;
#Override
public void stateChanged(ChangeEvent e) {
if (!(e.getSource() instanceof PiecePane)) { return; }
PiecePane piece = (PiecePane) e.getSource();
// Want to ignore events from the selected piece, as this
// might interfer with the changing of the pieces
if (selectedPiece == piece) { return; }
if (selectedPiece != null) {
selectedPiece.setSelecetd(false);
selectedPiece = null;
}
selectedPiece = piece;
}
};
for (int index = 0; index < 5 * 5; index++) {
PiecePane pane = new PiecePane();
pane.addChangeListener(listener);
add(pane);
}
}
}
public class PiecePane extends JPanel {
private boolean selecetd;
private Color selectedBackground;
private Color normalBackground;
private MouseListener mouseListener;
public PiecePane() {
setBorder(new LineBorder(Color.DARK_GRAY));
mouseListener = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
setSelecetd(true);
}
};
setNormalBackground(Color.BLUE);
setSelectedBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
#Override
public void addNotify() {
super.addNotify();
addMouseListener(mouseListener);
}
#Override
public void removeNotify() {
super.removeNotify();
removeMouseListener(mouseListener);
}
public void addChangeListener(ChangeListener listener) {
listenerList.add(ChangeListener.class, listener);
}
public void removeChangeListener(ChangeListener listener) {
listenerList.remove(ChangeListener.class, listener);
}
protected void fireSelectionChanged() {
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
if (listeners.length == 0) {
return;
}
ChangeEvent evt = new ChangeEvent(this);
for (int index = listeners.length - 1; index >= 0; index--) {
listeners[index].stateChanged(evt);
}
}
public boolean isSelected() {
return selecetd;
}
public void setSelecetd(boolean selecetd) {
if (selecetd == this.selecetd) { return; }
this.selecetd = selecetd;
updateSelectedState();
fireSelectionChanged();
}
public Color getSelectedBackground() {
return selectedBackground;
}
public void setSelectedBackground(Color selectedBackground) {
this.selectedBackground = selectedBackground;
updateSelectedState();
}
public Color getNormalBackground() {
return normalBackground;
}
public void setNormalBackground(Color normalBackground) {
this.normalBackground = normalBackground;
updateSelectedState();
}
protected void updateSelectedState() {
if (isSelected()) {
setBackground(getSelectedBackground());
} else {
setBackground(getNormalBackground());
}
}
}
}
I created a toggle button.
You set the primary color and the alternate color in the class constructor.
When you call the switchColors method, the JButton background changes from the primary color to the alternate color. When you call the switchColors method again, the JButton background changes from the alternate color to the primary color.
In the following example, I put the switchColors method in the actionListener so you can see the color change. Each time you left-click on the JButton, the background color changes.
You would call the switchColors method when you want the JButton background to change from blue to red, and again when you want the JButton background to change from red to blue. It's under your control.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ButtonDemo extends JButton
implements ActionListener {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Button Demo");
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout());
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo(Color.BLUE,
Color.RED));
frame.setSize(300, 300);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
});
}
private boolean primaryBackground;
private Color primaryColor;
private Color alternateColor;
public ButtonDemo(Color primaryColor,
Color alternateColor) {
this.primaryColor = primaryColor;
this.alternateColor = alternateColor;
this.primaryBackground = true;
this.setText("BUTTON TEXT");
this.setBackground(primaryColor);
this.addActionListener(this);
}
public void switchColors() {
primaryBackground = !primaryBackground;
Color color = primaryBackground ? primaryColor :
alternateColor;
this.setBackground(color);
}
#Override
public void actionPerformed(ActionEvent e) {
switchColors();
}
}
If you want to change the background for a short while you can do it with swing Timer:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class ButtonDemo extends JButton implements ActionListener{
private static final int DELAY = 600; //milliseconds
private final Timer timer;
public ButtonDemo() {
this.setText("BUTTON TEXT");
this.addActionListener(this);
Color defaultCloor = getBackground();
timer = new Timer(DELAY, e-> setBackground(defaultCloor));
timer.setRepeats(false);
}
public static void main(String[] args){
JFrame frame = new JFrame();
JPanel contentPane = new JPanel();
frame.setContentPane(contentPane);
contentPane.add(new ButtonDemo());
frame.setSize(300, 200);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
timer.stop();
this.setBackground(Color.RED);
timer.start();
}
}
I'm trying to call my paintComponent method by using repaint but it is never being called. This is my first class:
public class start
{
public static void main(String[] args){
Frame f = new Frame();
f.createFrame();
}
}
And this is the class that I want the paintComponent method to be called to but all that happens is a blank frame appears:
import javax.swing.JButton;
import javax.swing.JComponent;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.image.*;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.Timer;
public class Frame implements Runnable,ActionListener
{
JFrame window = new JFrame("Frame");
int i = 0;
Canvas myCanvas = new Canvas();
public void createFrame(){
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(30, 30, 700, 500);
window.setFocusable(true);
window.setFocusTraversalKeysEnabled(false);
window.setVisible(true);
(new Thread(new Frame())).start();
}
public void run(){
Timer timer = new Timer (17,this);
timer.start();
}
public void actionPerformed(ActionEvent e){
myCanvas.updateGame();
myCanvas.render();
window.add(myCanvas);
}
}
class Canvas extends JPanel{
int x = 10;
int y = 10;
public void updateGame(){
x++;
}
public void render(){
repaint();
System.out.println("repaint");
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g.drawString("hi",x,y);
System.out.println("paint");
}
}
Repaint is called multiple times but paint is never called. Why isn't the paintComponent method being called by repaint?
Instead of creating a new frame, pass in the existing frame, I've commented the line below:
public void createFrame(){
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(30, 30, 700, 500);
window.setFocusable(true);
window.setFocusTraversalKeysEnabled(false);
window.setVisible(true);
(new Thread(new Frame())).start(); <--- instead of creating a new frame, pass in the existing frame
}
You should really consider the following improvements as well:
1) Don't name your class Frame, as it collides with Frame
2) Move the body of createFrame as well as the following three lines:
JFrame window = new JFrame("Frame");
int i = 0;
Canvas myCanvas = new Canvas();
Into a constructor and make these local variables like Canvas into member fields.
3) Remove the last line that creates the thread out of the constructor, and expose it as a method (e.g 'startAnimation') and call it after you've created your object.
EDIT:
Try this:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Frame implements Runnable, ActionListener
{
final JFrame window;
final Canvas myCanvas;
public Frame(){
this.window = new JFrame("Frame");
this.myCanvas = new Canvas();
this.window.add(this.myCanvas);
this.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.window.setBounds(30, 30, 700, 500);
this.window.setFocusable(true);
this.window.setFocusTraversalKeysEnabled(false);
this.window.setVisible(true);
}
public void startApp() {
final Thread t = new Thread(this);
t.start();
}
public void run(){
final Timer timer = new Timer (1000,this);
timer.start();
}
public void actionPerformed(ActionEvent e){
myCanvas.updateGame();
window.repaint();
}
public static void main(String[] args) {
final Frame f = new Frame();
f.startApp();
}
}
class Canvas extends JPanel {
int x = 10;
int y = 10;
public void updateGame() {
x++;
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g.drawString("hi", this.x, this.y);
System.out.println("paint");
}
}
Hi I have following classes, I want display content
(paintComponentor that panel with this rectangle from paint class)
inside my JFrame. I try already find out how to achieve this by
looking at different examples posted on this forum however this
doesn't help me I need simple example like panel inside frame with
paint component or something similar to understand how should work!
ps. don't hang me on tree because I am newbie jut ask question!!!
[I want something like this][1]
package scp;
import java.awt.*;
import javax.swing.*;
public class Panel extends JPanel {
public Panel() {
//this.setPreferredSize(new Dimension(200,200));
//panel = new Panel();
setVisible(true);
setLayout(new FlowLayout());
setSize(200, 300);
getRootPane();
}
#Override
public void paintComponent(Graphics g){
g.drawString("HEY",20,20);
g.drawRect(200, 200, 200, 200);
}
}
and
package scp;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.beans.EventHandler;
public class Frame extends JFrame {
JButton redButton;
JButton blueButton;
public Frame()
{
super("EventHandling");
setLayout(new FlowLayout());
redButton = new JButton("Red");
add(redButton);
blueButton = new JButton("Blue");
add(blueButton);
EventHandler h = new EventHandler();
redButton.addActionListener(h);
blueButton.addActionListener(h);
}
private class EventHandler implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (e.getSource()==redButton)
getContentPane().setBackground(Color.RED);
else if(e.getSource()==blueButton)
getContentPane().setBackground(Color.BLUE);
}
}
}
and
package scp;
import javax.swing.JFrame;
public class EventHandling {
public static void main(String[] args) {
Frame f = new Frame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(800,600);
f.setVisible(true);
f.getContentPane().add(new Panel());
}
}
[1]: http://i.stack.imgur.com/OJTrq.png
Start by taking a look at:
Painting in AWT and Swing
Performing Custom Painting
2D Graphics
This is probably the simplest I can make it...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth() - 100;
int height = getHeight() - 100;
int x = (getWidth() - width) / 2;
int y = (getHeight() - height) / 2;
g2d.setColor(Color.RED);
g2d.drawRect(x, y, width, height);
g2d.dispose();
}
}
}
Compound Example
This example uses an outer panel, which has an empty border applied to it, this pushes the content of the edges of the outer panel.
The inner panel (which is unchanged from the last example), as a light gray border applied to it so you can see it, the red rectangle is still been painted by the panels paintComponent method.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JPanel outer = new JPanel(new BorderLayout()) {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
};
outer.setBorder(new EmptyBorder(50, 50, 50, 50));
TestPane tp = new TestPane();
tp.setBorder(new LineBorder(Color.LIGHT_GRAY));
outter.add(tp);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(outer);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth() - 100;
int height = getHeight() - 100;
int x = (getWidth() - width) / 2;
int y = (getHeight() - height) / 2;
g2d.setColor(Color.RED);
g2d.drawRect(x, y, width, height);
g2d.dispose();
}
}
}