I am trying to use java swing GUI at the same time I am drawing 2Dgraphics for the game I am creating. My goal is to have a drop down over the top of the graphics. Whenever i try to make a button or drop down in swing I cannot see it. This I believe is the 2Dgrahpics covering the swing elements.
This is my class decleration and my JFrame creation:
public class Main extends JFrame{
public Main(){
setBackground(Color.LIGHT_GRAY);
setSize(1000,600);
setTitle("Scaling Tests");
setDefaultCloseOperation(3);
setVisible(true);
This is how I am double buffering and drawing the graphics:
public void paint(Graphics g){
dbImage = createImage(1000, 600);
dbg = dbImage.getGraphics();
draw(dbg);
g.drawImage(dbImage, 0, 0, this.getWidth(), this.getHeight() , this);
repaint();
}
public void draw(Graphics g){
g.setColor(Color.red);
g.fillRect(100, 100, 200, 200);
I have tried to draw a JLabel like this in the constructor and the draw method:
JLabel mylabel = new JLabel();
mylabel.setText("Hello World!");
mylabel.setBounds(0, 0, 1280, 720);
mylabel.setVisible(true); //unnecessary
this.add(mylabel);
This has not worked. I cannot see the Jlabel no matter where in the code I put it. I think there is some problem with the graphics covering it up.
Your problem is that you are breaking the painting chain because you didn't invoke super.paint() so none of the child components are painted.
However you should NOT override paint() on a JFrame.
Instead, custom painting is done by overriding paintComopnent() on a JPanel and then you add the panel to the frame. And don't forget to invoke super.paintComponent(g) as the first statement in the method.
Then you can add the JLabel to the panel.
Also, never invoked repaint() in a painting method. This will cause an infinite loop.
This works -except the label is all the background you have to use some layout manager to handle it
import java.awt.*;
import javax.swing.*;
public class Main extends JFrame{
public Main(){
setBackground(Color.LIGHT_GRAY);
setSize(1000,600);
setTitle("Scaling Tests");
setDefaultCloseOperation(3);
JLabel mylabel = new JLabel();
mylabel.setText("Hello World!");
mylabel.setBounds(0, 0, 1280, 720);
add(mylabel);
setVisible(true);
}
public static void main(String args[]) {
Main m=new Main();
}
public void paint(Graphics g){
Image dbImage = createImage(1000, 600);
Graphics dbg = dbImage.getGraphics();
draw(dbg);
g.drawImage(dbImage, 0, 0, this.getWidth(), this.getHeight() , this);
}
public void draw(Graphics g){
g.setColor(Color.red);
g.fillRect(100, 100, 200, 200);
}
}
Related
can someone help me to know why the whole jtextfield is not visible when adding it to a jpanel that has a painted image icon? here is my code for the sample. thanks :)
without typing anything on it, only part of it is visible.
import java.awt.*;
import javax.swing.*;
public class GraphicsMain extends JFrame{
Panel panel = new Panel();
JTextField tf = new JTextField(10);
public GraphicsMain() {
tf.setBackground(Color.red);
panel.setLayout(new FlowLayout());
panel.add(tf);
this.add(panel);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
}
public static void main(String[] args) {
new GraphicsMain();
}
}
class Panel extends JPanel{
int pixel;
Image image;
public Panel() {
//#1 create icon
image = new ImageIcon("sample.png").getImage();
this.setPreferredSize(new Dimension(250,250));
}
//#2 paint
public void paint(Graphics g){
Graphics g2d = (Graphics2D)g;
g2d.drawImage(image, 0, 0, null);
}
}
You've broken the paint chain (responsibility).
Take a look at:
Performing Custom Painting
Painting in AWT and Swing
to get a better understand of how painting works and how you're suppose to use.
You "could" try and fix it by doing something like...
#Override
public void paint(Graphics g){
super.paint(g);
Graphics g2d = (Graphics2D)g;
g2d.drawImage(image, 0, 0, this);
}
but this is just painting the image over the top of what was previously paint.
You "could" try and fix it by doing something like...
#Override
public void paint(Graphics g){
Graphics g2d = (Graphics2D)g;
g2d.drawImage(image, 0, 0, this);
super.paint(g);
}
But now the image isn't getting painted (because part of the paint workflow is to fill the component with the background color of the component)
Instead, you need to inject your code into a different point in the paint process.
You should be using paintComponent, as it's primary responsibility is to "paint the component", this is called before the children are painted, so it's a great place for painting the background, for example...
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics g2d = (Graphics2D)g;
g2d.drawImage(image, 0, 0, this);
}
This question already exists:
Java Graphics not showing on Mac even with overriding the paintComponent() method of the JPanel
Closed 2 years ago.
I'm new to Java and am trying to create a program in Swing following an Youtube Tutorial. Everything works fine in Windows but in Mac, the background image doesn't show up but only the menuBar(JLabel). I hope to get background image and JLabels in a same page.
Can someone please help me to continue in the right direction? I will put all the file codes so that understading the issue is better.
Thanks a lot in advance!
[Main.java]
package dynamic_beat_4;
public class Main {
public static final int SCREEN_WIDTH = 1280;
public static final int SCREEN_HEIGHT = 720;
public static void main(String[] args) {
new DynamicBeat();
}
}
[Dynamic Beat.java]
package dynamic_beat_4;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class DynamicBeat extends JFrame {
private Image screenImage;
private Graphics screenGraphic;
private Image introBackground = new ImageIcon(Main.class.getResource("../images/introBackground(Title).jpg"))
.getImage();
private JLabel menuBar = new JLabel(new ImageIcon(Main.class.getResource("../images/menuBar.png")));
public DynamicBeat() {
setUndecorated(true);
setTitle("Dynamic Beat Game");
setSize(Main.SCREEN_WIDTH, Main.SCREEN_HEIGHT);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setBackground(new Color(0, 0, 0, 0));
setLayout(null);
menuBar.setBounds(0, 0, 1280, 30);
add(menuBar);
Music introMusic = new Music("introMusic.mp3", true);
introMusic.start();
}
public void paint(Graphics g) {
screenImage = createImage(Main.SCREEN_WIDTH, Main.SCREEN_HEIGHT);
screenGraphic = screenImage.getGraphics();
screenDraw(screenGraphic);
g.drawImage(screenImage, 0, 0, null);
}
public void screenDraw(Graphics g) {
g.drawImage(introBackground, 0, 0, null);
paintComponents(g);
this.repaint();
}
}
Some major points.
don't call repaint inside of a paint method. This doesn't make sense.
the preferred painting technique of swing is to override paintComponent.
Don't override Window#paint and if you do, call super.paint(g). (As per the linked javadoc.)
Calling paintComponents(g) with the graphics object of a temporary image is unnecessary at best. Swing handles buffering.
I'm amazed this worked on any platform.
I think the easiest fix for this is to create a JPanel.
public DynamicBeat() {
setUndecorated(true);
setTitle("Dynamic Beat Game");
setSize(Main.SCREEN_WIDTH, Main.SCREEN_HEIGHT);
setResizable(false);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setBackground(new Color(0, 0, 0, 0));
JPanel panel = new JPanel(){
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(introBackground, 0, 0, this);
}
};
panel.setLayout(null);
menuBar.setBounds(0, 0, 1280, 30);
panel.add(menuBar);
setContentPane(panel);
Music introMusic = new Music("introMusic.mp3", true);
introMusic.start();
}
You might want to refer to this painting in awt and swing.
Some further tips, don't extend JFrame, and do your GUI work on the EDT.
I hope that I used the question function correctly this time. I have been confused by a question from yesterday to now. I used Google search to ask my java teacher and did not solve my problem.
When I use repaint, the child components in the shaped JPanel will exceed their display area. As in the following figures,
This is the effect I want
But when I use repaint somethings changes.
The button doesn’t seem right at first.
But sometimes the button will return to normal
these are my code. I use repaint because the information I checked tells me that I can use it. Repaint to achieve animation effects.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;
class GPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.clip(new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), getWidth(), getHeight()));
g2d.setPaint(Color.BLUE);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
}
public class MainComponentOverflow {
public static void main(String[] args) {
JFrame frame = new JFrame();
// This is a panel with a shape
GPanel panel = new GPanel();
// This one is the effect I am looking for, the rectangle is displayed in the Panel.
//panel.add(new Normal());
// The following two will have problems, the rectangle will be displayed outside the Panel
//panel.add(new Problem1());
panel.add(new Problem2());
//panel.add(new JButton("This will also cause problems, but it may also display properly when I resize the window."));
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
class Normal extends JPanel {
public Normal() {
setPreferredSize(new Dimension(500, 500));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
class Problem1 extends JPanel implements ActionListener {
public Problem1() {
Timer timer = new Timer(16, this);
timer.start();
setPreferredSize(new Dimension(500, 500));
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
class Problem2 extends JPanel implements ActionListener {
public Problem2() {
Timer timer = new Timer(16, this);
timer.start();
setPreferredSize(new Dimension(500, 500));
}
#Override
public void actionPerformed(ActionEvent e) {
setBackground(new Color((float) Math.random(), (float)Math.random(), (float)Math.random()));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
}
When the frame is painted first, the clip will be set in GPanel, and then the children will be painted in Problem1 with the same clip, so it will work.
However, when you repaint Problem1, GPanel will not be repainted first, so the clip isn’t set, and there is no clip to restrict Problem1.
If instead of repainting Problem1 you repaint the parent, GPanel, it will resolve your problem.
Another solution would be to put the clip in Problem1 too.
Note that you can replace your RoundRect2D with an Ellipse2D, as you use it to paint an ellipse.
I'm having issues with this code. For some reason, paintComponent(Graphics g) simply doesn't work and there doesn't seem to be an answer how to force it to. This is my code:
import javax.swing.JFrame;
public class Robotron extends JFrame
{
public Robotron ()
{
//add(this); This one gave me an error
setSize(800, 600);
new TestFrame();
setVisible(true);
}
public static void main(String [ ] args)
{
new Robotron();
}
and this is my TestFrame class that has the paintComponent function:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class TestFrame extends JPanel
{
public void paintComponent(Graphics g)
{
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.YELLOW);
g.fillRect(100, 100, 10, 30);
System.out.println("Abdullah Paint");
}
public TestFrame()
{
setFocusable(true);
repaint();
}
}
What can I do in order to make paintComponent actually play. What I get in the end is just an empty JFrame, with no running of the System.out.println thingy.
Thanks a whole lot, been tackling this for a long time.
You're not adding anything to the JFrame, because of this
//add(this);
Here, you were trying to add the component to itself, which is not going to fly.
Instead, you need to add the TestFrame instance to the Frame.
add(new TestFrame());
setSize(800, 600);
setVisible(true);
You need to add the panel to the frame:
public Robotron ()
{
//add(this); This one gave me an error
setSize(800, 600);
add(new TestFrame());
setVisible(true);
}
As mentioned by others, you need to add the panel to the frame:
public Robotron() {
add(new TestFrame());
setSize(800, 600);
setVisible(true);
}
As not mentioned by others, you need to call super.paintComponent(g) the first thing in your overridden method:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.YELLOW);
g.fillRect(100, 100, 10, 30);
System.out.println("Abdullah Paint");
}
Notes:
Don't call repaint() in the constructor. At best it does nothing.
Don't call setSize(...) for the frame, instead call pack(). You will need to override the getPreferredSize method in your panel for this.
I'm trying it to display a rectangle at the specified location but it isn't showing up. The background is magenta but the rectangle is not there.
Also: How can I access more colors besides the "Color.(insert very few options here)"
import javax.swing.*;
import java.awt.*;
class Screensaver {
private final static int FRAME_HEIGHT = 600;
private final static int FRAME_WIDTH = 600;
public static void main(String[] args){
JFrame win;
Container contentPane;
Graphics g;
win = new JFrame();
win.setSize(FRAME_WIDTH, FRAME_HEIGHT);
win.setVisible(true);
contentPane = win.getContentPane();
contentPane.setBackground(Color.MAGENTA);
g = contentPane.getGraphics();
g.setColor(Color.BLACK);
g.fillRect(80, 350, 400, 250);
}
}
You shouldn't be painting in main(); it would be better to extend JPanel, change paintComponent(), and add the panel to the JFrame.
public class PaintPanel extends JPanel {
public PaintPanel() {
setBackground(Color.MAGENTA);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g); // This paints the background
g.setColor(Color.BLACK);
g.fillRect(80, 350, 400, 250);
}
}
And in main():
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.add(new PaintPanel());
frame.setVisible(true);
}
If you want to make your own Colors, you can use the new Color(int red, int green, int blue) constructor.
If you're going to draw stuff create a class that inherits from a Swing container, JComponent, JPanel, etc. and override the paint(Graphics g) method. If you see the magenta background then contentPane must have been added. What's probably happening is its painting the magenta background over your rectangle, but that's just a guess. Try this...
public class ContentPane extends JComponent {
public ContentPane() {
}
#Override
public void paint(Graphics g) {
g.setColor(Color.MAGENTA);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.BLACK);
g.fillRect(80, 350, 400, 250);
}
}
Then in your main class instantiate an object of the ContentPane class and add it to your JFrame. The call to repaint() is probably unnecessary but that will make sure it gets painted. You can also try messing around with the paintComponent(Graphics g) method, there is a difference between the two, I believe its the order they're called from the update method but I'm probably wrong about that, however that should solve your problem.
As for colors, consult the API. You can pass RGB values into the Color constructor to create all sorts of colors. Color color = new Color(int red, int green, int blue). I think that is the easiest way to create custom colors but like I said its all in the API. Hope this helps.
Try this :
import javax.swing.*;
import java.awt.*;
class Screensaver {
private final static int FRAME_HEIGHT = 600;
private final static int FRAME_WIDTH = 600;
public static void main(String[] args) {
JFrame win;
Container contentPane;
win = new JFrame();
win.setSize(FRAME_WIDTH, FRAME_HEIGHT);
win.setVisible(true);
Component comp = new Component();
contentPane = (Container) win.getContentPane().add(comp);
}
}
class Component extends JComponent {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.magenta);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.BLACK);
g.fillRect(80, 350, 400, 250);
}
}
and about the color , you van create new Color and set the RED,GREEN,BLUE as you want , Try this :
g.setColor(new Color(red, green, blue));
The rectangle is drawn once, however every time the JFrames repaint() method is called it erases it and draws the basic Components. To add custom drawing in JFrames you have to override the paint method. Here I improved your code slightly to get you started down that path. As you can see you want to draw the box in the Paint method. I made a Container element that does your drawing and removed the background color, adding it to the paint method as well.
try this
import javax.swing.*;
import java.awt.*;
public class JavaApplication10 {
private final static int FRAME_HEIGHT = 600;
private final static int FRAME_WIDTH = 600;
public static void main(String[] args){
JFrame win = new JFrame();
win.setContentPane(new MyBoxContainer());
win.setSize(FRAME_WIDTH, FRAME_HEIGHT);
win.setVisible(true);
}
private static class MyBoxContainer extends Container {
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.MAGENTA);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.BLACK);
g.fillRect(80, 350, 400, 250);
}
}
}