Confusion with regarding to absolute positioning [duplicate] - java

In the below example, how can I get the JPanel to take up all of the JFrame? I set the preferred size to 800x420 but it only actually fills 792x391.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BSTest extends JFrame {
BufferStrategy bs;
DrawPanel panel = new DrawPanel();
public BSTest() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout()); // edited line
setVisible(true);
setSize(800,420);
setLocationRelativeTo(null);
setIgnoreRepaint(true);
createBufferStrategy(2);
bs = getBufferStrategy();
panel.setIgnoreRepaint(true);
panel.setPreferredSize(new Dimension(800,420));
add(panel, BorderLayout.CENTER); // edited line
panel.drawStuff();
}
public class DrawPanel extends JPanel {
public void drawStuff() {
while(true) {
try {
Graphics2D g = (Graphics2D)bs.getDrawGraphics();
g.setColor(Color.BLACK);
System.out.println("W:"+getSize().width+", H:"+getSize().height);
g.fillRect(0,0,getSize().width,getSize().height);
bs.show();
g.dispose();
Thread.sleep(20);
} catch (Exception e) { System.exit(0); }
}
}
}
public static void main(String[] args) {
BSTest bst = new BSTest();
}
}

If you are having only one panel in frame and nothing else then try this:
Set BorderLayout in frame.
Add panel in frame with BorderLayout.CENTER
May be this is happening because of while loop in JPanel.(Not sure why? finding actual reason. Will update when find it.) If you replace it with paintComponent(g) method all works fine:
public BSTest() {
//--- your code as it is
add(panel, BorderLayout.CENTER);
//-- removed panel.drawStuff();
}
public class DrawPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
System.out.println("W:" + getSize().width + ", H:" + getSize().height);
g2d.fillRect(0, 0, getSize().width, getSize().height);
}
}
//your code as it is.

Here's an alternative using pack instead.
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PackExample extends JFrame {
public PackExample(){
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(800,600));
panel.setBackground(Color.green);
add(panel);
pack();
setVisible(true);
}
public static void main(String[] args){
new PackExample();
}
}

This took me forever to figure out but its actually the simplest code ever.
Just create a parent panel and pass GridLayout then add your child panel like this.
JPanel parentPanel= new JPanel(new GridLyout());
JPanel childPanel= new JPanel();
parentPanel.add(childPanel);

If you want to fill the JFrame with the whole of JPanel you need to setUndecorated to true i.e. frame.setUndecorated(true);. But now you have to worry about your MAXIMIZE< MINIMIZE, and CLOSE Buttons, towards the top right side(Windows Operating System)

Related

JComponent not appearing

I'm trying to create a super simple component, and it's not appearing.
Component class:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
public class Player extends JComponent{
public Player()
{
}
public void paint(Graphics g)
{
g.setColor(Color.green);
g.fillRect(40,40,150,150);
}
}
Panel Class im adding it to:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;
import javax.swing.JPanel;
public class Game extends JPanel{
public Game()
{
this.setBackground(Color.yellow);
this.setPreferredSize(new Dimension(500,500));
Player p = new Player();
this.add(p);
}
}
And the JFrame:
import javax.swing.JFrame;
public class Launcher {
public static void main(String[] args) {
JFrame frame = new JFrame("Key Collector Demo");
frame.add(new Game());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
}
}
The only thing showing up is the yellow background.
JFrame and JPanel are working fine; this problem consistently happens to me when building jcomponents. What am I missing?
Any help would be greatly appreciated!
Coordinates that you are using to draw a component are defined in the space of that component.
If you do this:
public void paint(Graphics g)
{
g.setColor(Color.green);
System.out.println(getSize());
g.fillRect(40,40,150,150);
}
You will see that at the moment it is attempted to get drawn its size is 1x1. So drawing it from 40,40 obviously takes it out of the visible area of the component.
Now change the method to:
public void paint(Graphics g)
{
g.setColor(Color.green);
System.out.println(getSize());
setSize(45, 45);
g.fillRect(40,40,150,150);
}
Now you can see small filled rectangle. This is because you forced the size to be 45x45 and now there are 5 pixels to show in the space of the component while the remaining part is still out of the area.
Do not assume the Player panel to have a fixed size.
For a first test your paint method could look like this:
public void paint(Graphics g) {
g.setColor(Color.green);
g.fillRect(0,0,getWidth(),getHeight());
}
The next problem is that the component probably has no size or position. Add a LayoutManager to your panel and add the component:
public Game() {
this.setBackground(Color.yellow);
this.setPreferredSize(new Dimension(500,500));
this.setLayout(new BorderLayout());
Player p = new Player();
this.add(p, BorderLayout.CENTER);
}
With that, your player might take the full space and you see green instead of yellow. Play around with the LayoutManager and the player's preferredSize.

Java Swing Scroll through drawing

Im trying to add a JScrollpane to my JPanel. The problem is that the scrollpane doesn't recognize that my drawing is outside the frame. So how do I add the JScrollpane correctly?
Main class:
public MainFrame() extends JFrame{
public MainFrame() {
Container container = getContentPane();
container(new BorderLayout());
container.add(new JScrollPane(new Drawing()));
setSize(1280,720);
setVisible(true);
}
Drawing class:
public class Drawing() extends JPanel {
#Override
protected void paintComponent(Graphics g) {
g.drawLine(10, 100, 30000, 10);
}
}
There are a couple of errors in your code, let's step through each of them:
You're extending JFrame, and you should avoid it, see: Extends JFrame vs. creating it inside the program for more information about it. You're actually not changing its behavior so it's not needed to extend it.
For your JScrollPane to show the whole line, you need to change your window's size to be the same size of your line (as shown in this answer by #MadProgrammer).
Related to point 2, avoid the use of setSize(...) and instead override getPreferredSize(): See Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? for more information
You forgot to call super.paintComponent(...) method in your paintComponent() method.
Related to points 2, 3, you need to call pack() so Swing calculates the best preferred size for your component.
See this example:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class LongDraw {
private JFrame frame;
private Drawing drawing;
public static void main(String[] args) {
SwingUtilities.invokeLater(new LongDraw()::createAndShowGui);
}
private void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
drawing = new Drawing();
JScrollPane scroll = new JScrollPane(drawing);
frame.add(scroll);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class Drawing extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawLine(10, 100, 3000, 10);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(3000, 500);
}
}
}
Which produces something similar to this:

java graphics2D inside JPanel

I am trying to draw some simple shapes onto a JPanel but am having some difficulty. Apologies if this question appears to have been answered before but the other answers don't seem to help.
I followed a simple tutorial and was successful in drawing some basic shapes onto a JFrame, but when I moved the code how it was into a new class which extends JPanel, nothing appears on screen.
public class TestingGraphics extends JFrame{
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
new TestingGraphics();
}
public TestingGraphics(){
this.setSize(1000,1000);
this.setPreferredSize(new Dimension(1000,1000));
this.setTitle("Drawing tings");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(new TestingPanelGraphics(), BorderLayout.CENTER);
this.setVisible(true);
}
public class TestingPanelGraphics extends JPanel {
public TestingPanelGraphics(){
this.setSize(1000,1000);
this.setPreferredSize(new Dimension(1000,1000));
this.add(new DrawStuff(), BorderLayout.CENTER);
revalidate();
repaint();
this.setVisible(true); //probably not necessary
}
private class DrawStuff extends JComponent{
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D graph2 = (Graphics2D) g;
graph2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Shape rootRect = new Rectangle2D.Float(100, 100, 1000, 500);
graph2.setColor(Color.BLACK);
graph2.draw(rootRect);
}
I've tried setting preferred size, and revalidating and repainting.
I've added a call to super.paintComponent, although neither of those two were necessary when I was drawing straight onto a JFrame.
I ensured I was overriding paintComponent and changed it from public to protected. All following advice from similar threads, but nothing seems to work. I've stepped through in debugger mode and ensured it goes into the right method, and even watched it go into the paintManager, but still nothing appears on the window.
You've forget to set the appropriate layout manager.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestingGraphics extends JFrame{
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
new TestingGraphics();
}
public TestingGraphics(){
this.setSize(1000,1000);
this.setPreferredSize(new Dimension(1000,1000));
this.setTitle("Drawing tings");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(new TestingPanelGraphics(), BorderLayout.CENTER);
this.setVisible(true);
}
public class TestingPanelGraphics extends JPanel {
public TestingPanelGraphics(){
setLayout(new BorderLayout());
this.setPreferredSize(new Dimension(1000,1000));
this.add(new DrawStuff(), BorderLayout.CENTER);
revalidate();
repaint();
this.setVisible(true); //probably not necessary
}
private class DrawStuff extends JComponent{
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D graph2 = (Graphics2D) g;
graph2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Shape rootRect = new Rectangle2D.Float(100, 100, 1000, 500);
graph2.setColor(Color.BLACK);
graph2.draw(rootRect);
}
}
}
}
When you extends JFrame your default layout is the BorderLayout, but when you extends JPanel your default layout is the FlowLayout.

Java Swing/Graphics - repaint() or validate() doesn't work?

I'm from Germany. My English isn't very good but I try to do as less mistakes as possible. In addition it's my first question in this community and I hope I will get a useful and helpful answer (I've asked Google for more than 20 times)
So, I've wrote a program that paints two rectangles in different colors. When I click on a button, the color of one of these rectangles should change but it doesn't do so. I've tried repaint(), validate() and something I don't understand: pack()
Nothing helps. The color changes when I resize the windows but it should changes when I click the button...
Does somebody have an idea or the answer for this problem?
My code:
import java.awt.Graphics2D;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
#SuppressWarnings("serial")
public class Test extends JFrame {
public static boolean buttonClicked = false;
public Test() {
initComponents();
}
private void initComponents() {
zeichne z = new zeichne();
JFrame frame = new JFrame();
frame.setTitle("Grafiktest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
Dimension dm = new Dimension(500,500);
frame.setMinimumSize(dm);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JButton button = new JButton("Push me!");
button.setSize(100, 50);
button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonActionPerformed(evt);
}
});
panel.add(z);
panel.add(button, BorderLayout.SOUTH);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new Test();
}
private void buttonActionPerformed(java.awt.event.ActionEvent evt){
if(buttonClicked == false)
buttonClicked = true;
else
buttonClicked = false;
repaint();
}
public static boolean getClicked() {
return buttonClicked;
}
}
#SuppressWarnings("serial")
class zeichne extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawRect(0, 0, 150, 100);
g2.setColor(Color.black);
g2.fillRect(0, 0, 150, 100);
boolean clicked = Test.getClicked();
if(clicked) {
g2.setColor(Color.red);
}
else {
g2.setColor(Color.gray);
}
g2.fillRect(10,10,130,80);
System.out.println(g2.getColor());
}
}
The properties of a components should be defined within the component. For example when you use a JLabel you can use setText(...), setForeground(...), setFont(...) etc. to change the state of the label and then the label will repaint itself.
So when you do custom painting you should do the same thing. That is in your "Zeichne" class you create a method to change the state of the class like setSelected(...). So your code might be something like:
public void setSelected(boolean selected)
{
this.selected = selected;
repaint();
}
You would also need to create the isSelected() method so you can access the state of the property. Then in the paintComponent(...) method you can do:
g2.setColor( selected ? Color.RED : Color.GRAY );
g2.fillRect(10,10,130,80);
Finally in the ActionListener the code would be:
z.setSelected( !z.isSelected() );
I get it!
The extension of JFrame and the additional declaration of a JFrame was the problem. I've deleted the declaration, put the super() into the method Test() and modulated the used methods of JFrame. Now it's working.
Thanks for your help!

Align panels with backgrounds correctly?

I recently started with Java GUIs a few weeks ago and I have a difficulty with alignment.
Basically, I'm trying to have two Panels with a different background image (top Bar and content) and I want to align them one after another.
The problem is, that I can't use BorderLayout.NORTH and BorderLayout.SOUTH, because the background image loses his original size and gets very tiny.
How can I align them correctly, without losing the original size?
Here's my code:
package main;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ImageTest {
public static void main(String[] args) {
ImageFrame frame = new ImageFrame("topBar.png", "contentImage.png");
frame.setSize(640,480);
frame.setVisible(true);
}
}
class ImagePanel extends JPanel {
private Image img;
public ImagePanel(String img) {
this(new ImageIcon(img).getImage());
}
public ImagePanel(Image img) {
this.img = img;
}
public void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, null);
}
}
class ImageFrame extends JFrame {
public ImageFrame(String topBar, String body) {
setLayout(new BorderLayout());
ImagePanel topPanel = new ImagePanel(topBar);
ImagePanel bodyPanel = new ImagePanel(body);
add(topPanel, BorderLayout.NORTH);
add(bodyPanel, BorderLayout.SOUTH);
pack();
}
}
There are a number of issues that popup out at me
You're not calling super.paintComponent. This is very important and can not be understated
You really should be using ImageIO to load your images. Ala from the fact it supports a wider range of image formats, it also loads images concurrent and throws useful exceptions when something goes wrong
You're not supplying any preferredSize values. This is used by the layout manager to decide how best to layout your component. Remember though, this are only hints and layout managers are well within there rights to ignore them
Check out Reading/Loading an Image for more details on ImageIO
..the background image loses his original size and gets very tiny.
That is because the preferred size for a panel is 0x0 until components are put in it.
There are at least two ways to solve this:
Add content to the panels.
Override getPreferredSize() to return the Dimension of the image.
The first is optimal, but I'll show how to do the 2nd (less code).
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ImageTest {
public static void main(String[] args) {
ImageFrame frame = new ImageFrame();
//frame.setSize(640,480);
frame.pack();
frame.setVisible(true);
}
}
class ImagePanel extends JPanel {
private Image img;
public ImagePanel(String img) {
this(new ImageIcon(img).getImage());
}
public ImagePanel(Image img) {
this.img = img;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// a panel IS an ImageObserver, so use it here.
g.drawImage(img, 0, 0, this);
}
#Override
public Dimension getPreferredSize() {
int w = img.getWidth(this);
int h = img.getHeight(this);
return new Dimension(w,h);
}
}
class ImageFrame extends JFrame {
public ImageFrame() {
setLayout(new BorderLayout(2,2));
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
ImagePanel topPanel = new ImagePanel(new BufferedImage(200,20,BufferedImage.TYPE_INT_RGB));
ImagePanel bodyPanel = new ImagePanel(new BufferedImage(200,100,BufferedImage.TYPE_INT_RGB));
add(topPanel, BorderLayout.NORTH);
add(bodyPanel, BorderLayout.SOUTH);
pack();
}
}

Categories

Resources