i have been working on a flashing beacon on java using Jpanel, paint component and timers, however i am having trouble trying to get the buttons within the code to function. when the code is run, the flash button is supposed to prompt the beacon to start blinking/flashing whereas the steady button keeps it on the same colour. the alternating colours for the beacon are orange and grey.As well as this i cant seem to get rid of a button that keeps appearing in the top left of the window when the code is run. so far, this is what i have
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
/**
* Created by Enoch on 26/03/2015.
*/
class BelishaBeacon extends JPanel {
Color startLight, stopLight, color;
public void paintComponent(Graphics g) {
super.paintComponents(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(color);
Ellipse2D firstOval = new Ellipse2D.Double(130, 70, 50, 50);
g2.draw(firstOval);
g2.fill(firstOval);
g2.setColor(Color.BLACK);
Rectangle rect1 = new Rectangle(150, 119, 10, 35);
g2.draw(rect1);
g2.fill(rect1);
g2.setColor(Color.WHITE);
Rectangle rect2 = new Rectangle(150, 150, 10, 35);
g2.draw(rect2);
g2.fill(rect2);
g2.setColor(Color.BLACK);
Rectangle rect3 = new Rectangle(150, 180, 10, 35);
g2.draw(rect3);
g2.fill(rect3);
g2.setColor(Color.WHITE);
Rectangle rect4 = new Rectangle(150, 210, 10, 35);
g2.draw(rect4);
g2.fill(rect4);
g2.setColor(Color.BLACK);
Rectangle rect5 = new Rectangle(150, 240, 10, 35);
g2.draw(rect5);
g2.fill(rect5);
g2.setColor(Color.WHITE);
Rectangle rect6 = new Rectangle(150, 270, 10, 35);
g2.draw(rect6);
g2.fill(rect6);
g2.setColor(Color.BLACK);
Rectangle rect7 = new Rectangle(150, 300, 10, 35);
g2.draw(rect7);
g2.fill(rect7);
g2.setColor(Color.WHITE);
Rectangle rect8 = new Rectangle(150, 330, 10, 35);
g2.draw(rect8);
g2.fill(rect8);
g2.setColor(Color.BLACK);
Rectangle rect9 = new Rectangle(150, 360, 10, 35);
g2.draw(rect9);
g2.fill(rect9);
g2.setColor(Color.WHITE);
Rectangle rect10 = new Rectangle(150, 390, 10, 35);
g2.draw(rect10);
g2.fill(rect10);
}
public BelishaBeacon() {
startLight = Color.ORANGE;
stopLight = Color.LIGHT_GRAY;
color = startLight;
new Blinker(this);
setBackground(Color.white);
}
public void blink()
{
color = (color == startLight ? stopLight : startLight);
repaint();
}
}
//
class Blinker
{
BelishaBeacon blinkPanel;
public Blinker(BelishaBeacon bp)
{
blinkPanel = bp;
new Timer(500, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
blinkPanel.blink();
}
}).start();
}
}
//
class BelishaBeaconViewer extends JFrame {
JButton jbtFlash = new JButton("Flash");
JButton jbtSteady = new JButton("Steady");
JPanel bPanel = new JPanel();
BelishaBeacon bBPanel = new BelishaBeacon();
public BelishaBeaconViewer() {
bPanel.add(jbtFlash);
this.add(bPanel, BorderLayout.SOUTH);
bPanel.add(jbtSteady);
this.add(bBPanel, BorderLayout.CENTER);
jbtFlash.addActionListener(new FlashListener());
jbtSteady.addActionListener(new SteadyListener());
}
class FlashListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
repaint();
}
}
class SteadyListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
repaint();
}
}
public static void main(String[] args) {
JFrame bBFrame = new BelishaBeaconViewer();
bBFrame.setTitle("Belisha Beacon");
bBFrame.setSize(300, 300);
bBFrame.setDefaultCloseOperation((JFrame.EXIT_ON_CLOSE));
bBFrame.setVisible(true);
}
}
i cant seem to get rid of a button that keeps appearing in the top left of the window
//super.paintComponents(g); // typo
super.paintComponent(g); // should be
Don't start the Timer automatically.
The FlashListener should start the Timer, no need for the repaint
The SteadyListner should stop the Timer, no need for the repaint.
Related
I have to do a little Game in Java Swing for school. I created some gifs for it and wanted to put them in and I did, but the problem is that the gifs flicker sometimes. I really can't find anything on the Internet and honestly I don't even know where to start to look exactly.
My code:
import javax.swing.*;
import java.awt.*;
import java.net.URL;
public class Chicken extends JFrame {
private int canvasWidth = 560;
private int canvasHeight = 480;
private Color sideGreen = new Color(14, 37, 14);
private Color gapGreen = new Color(56, 148, 56);
private Color edgeGreen = new Color(49, 129, 49);
private Image chicken;
private Image cookie;
private DrawCanvas canvas;
public Chicken() {
canvas = new DrawCanvas();
canvas.setPreferredSize(new Dimension(canvasWidth, canvasHeight));
try {
addImages();
} catch (Exception ex) {
ex.printStackTrace();
}
Container cp = getContentPane();
cp.add(canvas);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
setTitle("Chicken");
pack();
setVisible(true);
}
private class DrawCanvas extends JPanel {
#Override
public void update(Graphics g) {
paintComponent(g);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
setDoubleBuffered(true);
setBackground(Color.BLACK);
g2.setColor(sideGreen);
g2.fillRect(0, 0, 80, canvasHeight);
g2.fillRect(canvasWidth - 80, 0, 80, 480);
g2.setColor(gapGreen);
g2.fillRect(80, 0, 400, 100);
g2.fillRect(80, canvasHeight - 100, 400, 100);
g2.setColor(edgeGreen);
g2.fillRect(80, 80, 400, 20);
g2.fillRect(80, canvasHeight - 100, 400, 20);
g2.drawImage(cookie, 85, 5, this);
g2.drawImage(chicken, 150, 120, this);
}
}
private void addImages() throws Exception {
ImageIcon iconCookie = new ImageIcon(new URL("https://i.stack.imgur.com/1PcWC.gif"));
Image cookieimage = iconCookie.getImage();
Image newimg = cookieimage.getScaledInstance(70, 70, Image.SCALE_DEFAULT);
iconCookie = new ImageIcon(newimg);
ImageIcon iconChicken = new ImageIcon(new URL("https://i.stack.imgur.com/qJA7G.gif"));
Image chickenimage = iconChicken.getImage();
Image newimgc = chickenimage.getScaledInstance(250, 250, Image.SCALE_DEFAULT);
iconChicken = new ImageIcon(newimgc);
chicken = iconChicken.getImage();
cookie = iconCookie.getImage();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new Chicken());
}
}
Is there something wrong in the code? Or is there another way to do it and I've just done it wrong? The gifs should be fine, I've created them myself and they look fine when I view them from my PC.
Chicken
Cookie
Edit
Found out that the chicken isn't flickering when I remove the cookie, but I don't know why.
Remove setDoubleBuffered(true); from paintComponent. Probably temptative code. You could call it in the constructor, but by default double buffering is on. Move setBackground(Color.BLACK); to the constructor.
Then remove the update method.
You normally do not need to call super.paintComponent();. Comment it out, and try to see a change.
You might do setContentPane(canvas).
Should there still be a problem, then it is due to the inner workings of gif handling.
So I have a custom JComponent (An almost completed button, if you will). Here is the source code to the class:
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class LukeButton extends JComponent implements MouseListener{
//ArrayList of listeners
private final ArrayList<ActionListener> listeners = new ArrayList<ActionListener>();
Shape rec = new RoundRectangle2D.Float(10, 10, 110, 60, 50, 75);
BasicStroke border = new BasicStroke(5);
SpringLayout layout = new SpringLayout();
private String text;
public LukeButton(String text){
this.text = text;
this.setLayout(layout);
this.addMouseListener(this);
}
//Adds a listeners to the list
public void addActionListener(ActionListener e){
listeners.add(e);
}
//Called when button is provoked
public void fireActionListeners(){
if(!listeners.isEmpty()){
ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "LukeButton");
for(ActionListener l: listeners){
l.actionPerformed(evt);
}
}
}
//Listens for click on my component
public void mousePressed(MouseEvent e){
if(rec.contains(e.getPoint())){
rec = new RoundRectangle2D.Float(10, 10, 100, 55, 50, 75);
repaint();
fireActionListeners();
}
}
public void mouseReleased(MouseEvent e){
if(rec.contains(e.getPoint())){
rec = new RoundRectangle2D.Float(10, 10, 110, 60, 50, 75);
repaint();
}
}
//When mouse enters, make border bigger
public void mouseEntered(MouseEvent e){
border = new BasicStroke(8);
repaint();
}
//When mouse leaves, make border smaller
public void mouseExited(MouseEvent e){
border = new BasicStroke(5);
repaint();
}
public Dimension getPreferredSize(){
return new Dimension(130, 80);
}
//Draws my button
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.BLACK);
g2.setStroke(border);
g2.draw(rec);
g2.setColor(new Color(0, 204, 204));
g2.fill(rec);
g2.setColor(Color.BLACK);
g2.drawString(text, 47, 45);
}
//Methods that must be over written.
public void mouseClicked(MouseEvent e){
}
}
My problem is that I do not know how to center the text variable (More or less what the variable consists of) based on the size of the String. The beggining of the String is always in a fixed point. For example if the text variable is equal to something short, the string is going to be far on the left. But if the string is too long, it goes far off the right side of the component. Does anyone know how to center my text variable so it changes it's position based on the size of the string(or a different/better solution of coarse)? Thanks for taking your time to read :)
You can get the Rectangle required to paint the text by using:
FontMetrics fm = g2d.getFontMetrics();
Rectangle2D rect = fm.getStringBounds(text, g2d);
Then to center the text you would get the x/y positions using something like:
int x = (getSize().width - rect.width) / 2;
int y = ((getSize().height - rect.height / 2) + rect.height;
Well the title explains it, basically the setBounds(int x, int y, int width, int height) method isn't working like I want it too as nothing is being displayed. The point of this code is to get the text from some text fields then close that window and and convert them to JLabel objects to be displayed on the screen but it doesn't do that. Here are some code fragments:
public class Create implements ActionListener {
private JTextArea t1, t2, t3;
private String s1 = t1.getText();
private String s2 = t2.getText();
private String s3 = t3.getText();
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b1) {
dispose();
setVisible(false);
t1 = new JTextArea(7, 17);
t2 = new JTextArea(7, 17);
t3 = new JTextArea(7, 17);
JFrame frame2 = new JFrame();
frame2.add(new Test(s1,s2,s3));
frame2.setTitle("Title");
frame2.setSize(700,500);
frame2.setResizable(true);
frame2.setLocationRelativeTo(null);
frame2.setVisible(true);
}
}
}
New class Test:
import java.awt.Color;
import java.awt.Component;
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.Rectangle2D;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
#SuppressWarnings("serial")
public class Test extends JPanel implements ActionListener {
private int w = 250, velx = 2, x = 330;
Timer tm = new Timer(50,this);
public Test(String s1, String s2, String s3) {
setText(s1, s2, s3);
}
public void setText(String s1, String s2, String s3) {
JLabel label1 = new JLabel(s1);
label1.setBounds(100, 100, 500, 500);
JLabel label2 = new JLabel(s2);
label2.setBounds(75, 20, 100, 20);
JLabel label3 = new JLabel(s3);
label3.setBounds(100, 20, 100, 20);
}
}
*****String won't draw on top of rectangle*****
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawString("something", 300, 50);
g.drawString("something", 50, 100);
g.drawString("something", 50, 150);
}
public void paint(Graphics g){
tm.setInitialDelay(10000);
super.paint(g);
Graphics2D graph2 = (Graphics2D)g;
Shape Rect1 = new Rectangle2D.Float(330, 30, 250, 390);
graph2.setColor(Color.CYAN);
graph2.fill(Rect1);
Shape Rect2 = new Rectangle2D.Float(x, 30, w, 390);
graph2.setColor(Color.RED);
graph2.fill(Rect2);
tm.start();
}
You actually need to add those label to your JPanel , So that they can get Displayed
public void setText(String s1, String s2, String s3) {
JLabel label1 = new JLabel(s1);
label1.setBounds(100, 100, 500, 500);
JLabel label2 = new JLabel(s2);
label2.setBounds(75, 20, 100, 20);
JLabel label3 = new JLabel(s3);
label3.setBounds(100, 20, 100, 20);
add(label1);// Add the label to your current JPanel
add(label2);
add(label3);
}
When you need absolute positioning , you need to explicitly set the Layout to Null
JPanel#setLayout(null)
Update
How to draw Rectangle on JLabel .
override the paintComponent method of the JLabel. It should first call super.paintComponent, so you get whatever the JLabel contains, then add your own drawing code after that.
#override
public void paintComponent(Graphics g){
super.paintComponent(g)
Rectangle r = new Rectangle(xPos,yPos,width,height);
g.fillRect(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
I'm making a program where hovering over a grid will place an image into the cell hovered over. Currently I have it working so that only a color is filled in, but I have no idea how to make it so an image is drawn in instead. Here's my program:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
public class Test
{
Image img=Toolkit.getDefaultToolkit().getImage("img.gif");
public static void main(String[]args)
{
new Test();
}
public Test()
{
JFrame frame=new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PixelGrid());
frame.setSize(new Dimension(364,357));
frame.setVisible(true);
}
public class PixelGrid extends JPanel
{
private List<Shape>grid,square;
public PixelGrid()
{
grid=new ArrayList<>();
square=new ArrayList<>();
addMouseMotionListener(new MouseAdapter()
{
public void mouseMoved(MouseEvent e)
{
for(Shape shape:grid)
{
if(shape.contains(e.getPoint()))
square.add(shape);
}
repaint();
}
}
);
for(int row=0;row<5;row++)
{
for(int col=0;col<5;col++)
grid.add(new Rectangle(col*25+112,row*25+50,25,25));
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawLine(112,50,237,50);
g.drawLine(112,75,237,75);
g.drawLine(112,100,237,100);
g.drawLine(112,125,237,125);
g.drawLine(112,150,237,150);
g.drawLine(112,175,237,175);
g.drawLine(112,50,112,175);
g.drawLine(137,50,137,175);
g.drawLine(162,50,162,175);
g.drawLine(187,50,187,175);
g.drawLine(212,50,212,175);
g.drawLine(237,50,237,175);
Graphics2D g2=(Graphics2D)g;
for(Shape cell:square)
g2.fill(cell);
}
}
}
I want to make the image "img" become the "pixel" that is filled in. However, I'm confused on how to do this as I don't think I can use for-each loops and Graphics2D. If anyone can help, thanks so much!
Define ImageHolder class which has 2 fields shape and image.
class ImageHolder {
Shape shape;
Image img;
public void paint(Graphics2D g2) {
if (img!=null) {
g2.drawImage(img);
}
else {
g2.fill(shape);
}
}
}
Your grid should be List. On init all the ImageHolders have squares and null images. On click image is assigned to the clicked holder.
In the paintComponent() you just call the holder's paint() method
take a look at this one.
all you need to do is repalce your g2.fill(cell); with g2.drawImage(img,cell.getBounds().x,cell.getBounds().y,null);
read drawimage api here
for (Shape cell : square) {
//g2.fill(cell);
g2.drawImage(img,cell.getBounds().x,cell.getBounds().y,null);
System.out.println(cell.getBounds().x);
}
however use Dimention list or 2D list instead Shape in this case
complete code
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
public class Test {
Image img = Toolkit.getDefaultToolkit().getImage("img.gif");
public static void main(String[] args) {
new Test();
}
public Test() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PixelGrid());
frame.setSize(new Dimension(364, 357));
frame.setVisible(true);
}
public class PixelGrid extends JPanel {
int x=0;
int y=0;
private List<Shape> grid, square;
public PixelGrid() {
grid = new ArrayList<>();
square = new ArrayList<>();
addMouseMotionListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
for (Shape shape : grid) {
if (shape.contains(e.getPoint())) {
square.add(shape);
}
}
repaint();
}
}
);
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 5; col++) {
grid.add(new Rectangle(col * 25 + 112, row * 25 + 50, 25, 25));
}
}
}
public void paintComponent(Graphics g) {
System.out.println(x);
g.drawLine(112, 50, 237, 50);
g.drawLine(112, 75, 237, 75);
g.drawLine(112, 100, 237, 100);
g.drawLine(112, 125, 237, 125);
g.drawLine(112, 150, 237, 150);
g.drawLine(112, 175, 237, 175);
g.drawLine(112, 50, 112, 175);
g.drawLine(137, 50, 137, 175);
g.drawLine(162, 50, 162, 175);
g.drawLine(187, 50, 187, 175);
g.drawLine(212, 50, 212, 175);
g.drawLine(237, 50, 237, 175);
Graphics2D g2 = (Graphics2D) g;
//g2.drawImage(img,x,y,null);
for (Shape cell : square) {
//g2.fill(cell);
g2.drawImage(img,cell.getBounds().x,cell.getBounds().y,null);
System.out.println(cell.getBounds().x);
}
}
}
}
output>>
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tetris extends JFrame {
public Tetris() {
add(new GamePanel());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
setSize(800, 600);
setVisible(true);
setLocationRelativeTo(null);
setTitle("Tetris");
}
public class GamePanel extends JPanel {
public GamePanel(){
TetrisBoard tetraBoard= new TetrisBoard();
GridBagLayout layout= new GridBagLayout();
this.setLayout(layout);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 2;
c.gridy = 1;
c.ipadx = 190;
c.ipady = 390;
c.insets.left= 360;
layout.setConstraints(tetraBoard, c);
this.add(tetraBoard);
setBackground(Color.WHITE);
}
#Override
public void paint(Graphics g){
super.paint(g);
g.setFont(new Font("Birth Std", Font.PLAIN, 12));
g.setColor(Color.LIGHT_GRAY);
g.drawString("200", 36, 63);
g.drawString("200", 36, 88);
g.drawString("200", 36, 114);
}
}//GamePanel class
public class TetrisBoard extends JPanel implements Runnable{
private Thread animator= new Thread(this);
private final int DELAY= 50;
public TetrisBoard(){
setFocusable(true);
//setBackground(Color.WHITE);
setDoubleBuffered(true);
//this.setBackground(Color.BLACK);
setOpaque(false);
}
#Override
public void addNotify() {
super.addNotify();
animator = new Thread(this);
animator.start();
}//addNotify
#Override
public void paint (Graphics g){
super.paint(g);
g.drawRect (20, 30, 130, 50);
}//paint
#Override
public void run() {
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while (true) {
repaint();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = DELAY - timeDiff;
if (sleep < 0)
sleep = 2;
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
System.out.println("interrupted");
}
beforeTime = System.currentTimeMillis();
}
}
}//TetrisBoard class
public static void main(String[] args) {
Tetris t = new Tetris();
}
}
With this code the result is that it doesn't paint anything at all. I just want the background to be transparent not the images painted over the background, but it looks like the paint method doesn't paint if I setOpaque(false).
Edit: as requested I posted a simple code, TetraBoard is added to the GamePanel (using that GridBagLayout), and GamePanel is added to the frame, those 3 classes are separate files. I want TetraBoard to have a transparent background, so that I can see the background of GamePanel, but what I paint on tetraboard must be visible. If I setOpaque(false), TetraBoard is transparent, but it set on transparent everything I paint on it.
Edit: Assuming I understand what you're trying to do, replace the following line in the TetrisBoard constructor:
setOpaque(false);
with:
setBackground(new Color(0,0,0,0));
For example:
JPanel p = new JPanel() {
#Override
public void paintComponent(Graphics g) { // as suggested Andrew
g.setColor(Color.RED);
g.drawArc(0, 0, 100, 100, 0, 360); // arc will be painted on transparent bg
}
};
p.setBackground(new Color(0, 0, 0, 0)); // as suggested Perry
...
So, you have to do two actions:
1) override paintComponent(Graphics g) of JPanel
2) and set bg color to transparent: new Color(0, 0, 0, 0)