When I work with Jpanel, I see that while Y is below 50 I don`t see objects, as they are hidden under top panel. I need a way to hide top panel or make it possible to not to add 50 to Y each time. In this example, top of the circle is hidden:
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
class Draw extends JFrame{
public static int Framesize=1000;
public static void main(String []args){
Draw s=new Draw();
s.setVisible(true);
}
public Draw(){
JPanel panel=new JPanel();
setSize(Framesize,Framesize);
setVisible(true);
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
for (int i=0;i<=1000;i+=50) {
g2.draw(new Line2D.Float(i, 0, i, Framesize));
g2.draw(new Line2D.Float(0, i, Framesize, i));
}
g2.setPaint(Color.RED);
g2.draw(new Ellipse2D.Float(0,0,200,200));
g2.drawString("Test", 100, 150);
}
}
First of all you have to use the JPanel variable you've created (because it's not a good practice to paint directly in the JFrame as you were doing just because It can cause the problem you were having). Here is an example of the panel class:
class panel extends JPanel{
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
for (int i = 0; i <= 1000; i += 50) {
g2.draw(new Line2D.Float(i, 0, i, Draw.Framesize));
g2.draw(new Line2D.Float(0, i, Draw.Framesize, i));
}
g2.setPaint(Color.RED);
g2.draw(new Ellipse2D.Float(0, 0, 200, 200));
g2.drawString("Test", 100, 150);
}
}
Then add the panel class to the frame constructor
panel panel = new panel();
add(panel);
Finally remove the paint function from the main frame (because you have already defined it in the panel class).
However, there is no point in removing the upside bar (because, objects below 50 in Y axis will appear).
But if for some reason you still want to remove the upside bar then, in order to remove it you have to define in the constructor: setExtendedState(JFrame.MAXIMIZED_BOTH);
setUndecorated(true);
Finally remove the paint function from the main frame (because you have already defined it in the panel class).
Related
I'm trying to draw 2 triangles with Graphics 2d. When running the first segment, it's totally correct. But if I run the second segment that I add a panel below the "Graph", the triangles disappear. Could anybody help me with the issue?
Here's the code.
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Path2D;
public class Draw_A_Triangle extends JPanel {
public Draw_A_Triangle() {}
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
work(g2d, Color.RED,30,45,60,90,60,90);
work(g2d, Color.blue,15,22.5,30,45,30,45);
}
// set a method to draw the 2 triangles
public void work(Graphics2D g2d, Color c, double x1, double x2, double x3, double y1, double y2, double y3) {
Path2D.Double p = new Path2D.Double();
g2d.setColor(c);
p.moveTo(x1, y1);
p.lineTo(x2, y2);
p.lineTo(x3, y3);
g2d.fill(p);
g2d.draw(p);
}
public static void main(String[] args) {
//set the JFrame
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Draw Triangle");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBackground(Color.white);
frame.setSize(200, 200);
// //segment 1
// Draw_A_Triangle panel = new Draw_A_Triangle();
// frame.add(panel);
// frame.setVisible(true);
// segment 2
Draw_A_Triangle panel = new Draw_A_Triangle();
JPanel p = new JPanel();
p.add(panel);
frame.add(p);
frame.setVisible(true);
}
}
I recommend the following changes.
don't set the size of the frame. Set the size of the JPanel to eliminate the frame border from taking up panel space. This is overriding the method in the JPanel instance.
#Override
public Dimension getPreferredSize() {
return new Dimension(500,500);
}
Then do the following:
frame.pack() - size the frame based on layout requirements and size preferences of its components.
frame.setLocationRelativeTo(null) - centers frame on screen.
You're already subclassing JPanel so no need to create a new one. Just add panel to frame.
And the first thing in overidding paintComponent(Graphics g) should be
super.paintComponent(g); Otherwise, required functionality like setting the background color of the panel won't work.
and if you want to set the background of the panel, use panel.setBackground(<someColor>)
Draw_A_Triangle panel = new Draw_A_Triangle();
panel.setBackground(Color.white);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
I recommend you check out the Java Tutorials for more on painting. Go to Really Big Index and search the TOC for painting
I am trying to create a rectangle in the center of a jframe. I tried with insets but i had not any luck. I have made the following class for the rectangle:
public class RectDraw extends JComponent{
Shape rect;
public void paint(Graphics g){
Graphics2D graph2 = (Graphics2D)g;
graph2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
rect = new Rectangle2D.Float(50,50,15,15);
graph2.setPaint(Color.BLACK);
graph2.fill(rect);
graph2.draw(rect);
}
}
And the main:
public class TheMain{
public static void main(String[] args) {
Screen screen = new Screen();
RectDraw rect = new RectDraw();
screen.add(rect, BorderLayout.CENTER);
}
And this is the class screen:
public class Screen extends JFrame{
public Screen(){
this.setSize(500, 500);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setTitle("Testing");
this.getContentPane().setBackground(Color.GRAY);
this.setVisible(true);
}
}
So what i should change in order to put this rectangle in the center of the jframe?
Thanks!
You need to override your Screen's paintComponent method.
Such that your rectangle is width 50 height 100. Simply do some maths.
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D graph2 = (Graphics2D)g;
//To center the rectangle, we need to specify the center x,y points on the frame
//Divide width and height into two, and minus the width and height of the rectangle
graph2.drawRect(getWidth()/2 - 50/2, getHeight()/2 - 100/2, 50, 100);
}
having a problem with top insets not giving the proper value when painting ... i am looking for y to be just under the title bar but it is not working correctly and putting it 25 pixels from the top where as the title bar only accounts for about 14 pixels .
Game Frame :
import java.awt.Dimension;
import javax.swing.JFrame;
public class gameFrame extends JFrame {
static int width = 400;
static int height = 400;
static int topinset;
static int FPS = 30;
public gameFrame(){
gamePanel gamePanel = new gamePanel();
gamePanel.setPreferredSize(new Dimension(width,height));
Thread thread = new Thread(gamePanel);
this.add(gamePanel);
this.setResizable(false);
this.setSize(width, height);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
topinset = this.getInsets().top;
thread.start();
}
public static void main(String[] args){
gameFrame gameFrame = new gameFrame();
}
}
Game Panel :
import java.awt.Graphics;
import javax.swing.JPanel;
public class gamePanel extends JPanel implements Runnable {
public gamePanel(){
this.setBounds(0,0,gameFrame.width,gameFrame.height);
this.setVisible(true);
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawString("Width: "+ gameFrame.width + " Height: " + gameFrame.height, 0, gameFrame.topinset);
}
#Override
public void run() {
while(true){
repaint();
try {Thread.sleep(1000*gameFrame.FPS);}
catch (InterruptedException e) {}
}
}
}
You are doing your custom painting on the panel so there is no need to worry about the offsets of the frame. Just use the getWidth() and getHeight() methods to get the current size of the panel.
If you want your panel to be (400, 400), then override the getPreferredSize() method of your panel class to return that dimension. Then use frame.pack() and the frame will size itself properly to include the panel size and the frame decorations.
There is no need for static variables. Those variables should just be instance variables or constants.
There is no need for the setBounds() since the layout manager will determine the size/location of the panel in the frame.
There is no need to make the panel visible since is it visible by default.
Follow Java naming conventions. Class names should start with an upper case character.
Why are you doing custom painting? Why not just add a JLabel to the NORTH of the frame and display your text in the label?
Start by taking a look through Working with Text APIs
Text rendering is typically done from the base line, meaning text will painted above the y position you specify
As has already being stated, a components Graphics context is translated before it's painted so that the 0x0 position will be the top/left corner of the component
In the following example, the first String will not appear on the screen, as it's base line is along the top edge of the component, whereas the second String has being adjusted so that it's ascent line is along the top top
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics g2d = (Graphics2D) g.create();
FontMetrics fm = g2d.getFontMetrics();
g2d.drawString("Hello", 0, 0);
g2d.drawString("Hello", fm.stringWidth("Hello"), fm.getAscent());
g2d.dispose();
}
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);
}
}
}
I have not used Swing/G2D much, so please be patient.
I have the following class which is a component on my GUI (meant to be a kind of Canvas to draw on):
import javax.swing.*;
import java.awt.*;
public class DrawPanel extends JComponent{
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(Color.black);
g2.fillRect(0, 0, getWidth(), getHeight());
BrushStroke bs = new BrushStroke();
add(bs);
}
}
I have been trying to add the following to the above JComponent:
import javax.swing.*;
import java.awt.*;
public class BrushStroke extends JComponent{
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(Color.red);
g2.fillOval(0, 0, 10, 10);
}
}
The BrushStroke does not show on the DrawPanel.
I have been searching forever for an answer, and each example I look at seems to be contradictory.
If anybody has attempted what I am, then help would be greatly appreciated. Also, if I am taking the completely wrong approach, please do say.
You should never add a component to a panel in any painting method. The painting methods are invoked whenever Swing determines a component needs to be painted. Therefore you would be adding the component to the panel multiple times.
When you do custom painting you are responsible for overriding the getPreferredSize() method to give the size of the component. This way the layout managers can position the components properly. If you don't do this then the preferred size is 0, so there is nothing to paint.
Read the section from the Swing tutorial on Custom Painting for more information and examples.
On the JComponent.add method, the documentation says:
Note: If a component has been added to a container that has been
displayed, validate must be called on that container to display the
new component. If multiple components are being added, you can improve
efficiency by calling validate only once, after all the components
have been added.
You should refresh your DrawPanel after adding an element to it. Watch out not to do it in the painComponent method, you will end up in an infinite recursion.
Do the following instead:
DrawPanel drawPanel = new DrawPanel();
drawPanel.add(new BrushStroke());
drawPanel.repaint();
EDIT
Here is a fully working solution (extending JPanels instead of JComponent)
public static void main(String[] args){
JFrame frame = new JFrame();
DrawPanel drawPanel = new DrawPanel();
drawPanel.add(new BrushStroke());
frame.getContentPane().add(drawPanel);
frame.pack();
frame.setVisible(true);
}
class DrawPanel extends JPanel{
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(Color.black);
g2.fillRect(0, 0, getWidth(), getHeight());
}
#Override
public Dimension getPreferredSize(){
return new Dimension(100, 100);
}
}
class BrushStroke extends JPanel{
public void paintComponent(Graphics g){
this.setOpaque(false);
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(Color.red);
g2.fillOval(0, 0, 10, 10);
}
#Override
public Dimension getPreferredSize(){
return new Dimension(10, 10);
}
}
The output gives the following: