I've been coding a simulation for a traffic flow network in Java, and the class that is supposed to graphically model the network looks as follows:
public class Map extends JPanel {
BufferedImage truck1;
public Map() throws IOException{
truck1 = ImageIO.read(getClass().getResource("Truck.png"));
}
protected void paintcomponent (Graphics g) {
super.paintComponent(g);
g.drawImage(truck1, 50, 100, 300, 300, this);
}
}
In my main() function, I instance the object as follows at the very beginning of the function:
Frame F1 = new Frame();
F1.setLayout(new FlowLayout());
F1.setSize(500,500);
F1.setVisible(true);
Map map = new Map();
map.setOpaque(true);
F1.add(map);
F1.setVisible(true);
However, when I run the program, the only output is a blank window with a slightly darker grey small square exactly in the middle at the top of the window. I've added Truck.png to the project, and I can't see any reason why it shouldn't display properly. What am I doing wrong?
Components should be added to the frame before the frame is made visible.
You are using a FlowLayout for your frame. A FlowLayout respects the preferred size of all components. Your Map class doesn't have a preferred size so the size defaults to (0, 0) so there is nothing to paint. Override the getPreferredSize() method of the Map class to return the appropriate size for the component.
Related
I have a board game (think Monopoly) where multiple game pieces can be located on a single tile. I want to be able to arbitrarily place game pieces on the any given tile. I want the tile to have a background (image or just flat color) and be able to place up to 4 game pieces on the tile in a grid. I am currently using this code but the circles do not display.
tank.png is a 135 x 135 pixel background.
GraphicsTile:
public class GraphicsTile extends JPanel {
public static final Dimension SIZE = new Dimension(135, 135);
public static final GridLayout MGR = new GridLayout(4, 4);
public GraphicsTile() {
super();
setLayout(MGR);
initGraphics();
setSize(SIZE);
add(new CirclePanel());
}
private void initGraphics() {
JLabel panel = null;
try {
Image image = ImageIO.read(new File("tank.png"));
panel = new JLabel(new ImageIcon(image));
panel.setSize(SIZE);
} catch (IOException e) {
e.printStackTrace();
}
add(panel);
}
}
CirclePanel:
public class CirclePanel extends JPanel {
public CirclePanel() {
setSize(33, 33);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.RED);
Ellipse2D.Float circle = new Ellipse2D.Float(50, 50, 0, 0);
g2d.draw(circle);
g2d.fill(circle);
}
}
public class GraphicsTile {
I don't know how your code compiles since your GraphicsTile doesn't extend any Swing component yet you use methods like setLayout(...) and setSize(...) which implies you are trying to use it like a JPanel.
You should not be using setSize(...). A Swing component should have a preferred size. Then the layout manager will set the size and location of the component based on the rules of the layout manager. I'm guessing you have a problem because the preferred size is (0, 0).
I also have no idea how you add the GraphicsTile to the parent component. Again it looks like you are using setSize() when you should let the layout manager position the tiles on the game board.
Also, if you want to have a background image with circles on top then you need a hierarchical structure. That is you need something like:
panel
background image
circle component.
So my suggestions are:
CirclePanel needs to implement the getPreferredSize(...) method to return the size of your custom painting.
Your GraphicsTile class needs to extend JPanel. You would then override the paintComponent(...) method to draw your background image. Now you can add the CirclePanel instances to the this panel which will use the GridLayout.
I have tried many solutions but I do not know what is wrong with my code.
Basicaly I want to display the shapes in the window, FlowLayout does not display anything and BorderLayout displays the last one which is not what I want. Ignore the shape.draw() method, it just prints coordinates of the shape. Shape extends JComponent.
package Shapes;
import javax.swing.*;
import java.awt.*;
/**
* Created by Matej on 10/12/2016.
*/
public class TestShapes extends JFrame
{
//static Shape[] shapes = new Shape[3];
public static void main(String[] args)
{
Shape[] shapes = new Shape[3];
shapes[0] = new Circle(300,100,20);
shapes[1] = new Rectangle(100,100,40,60);
shapes[2] = new RedRectangle(200,200,20,30);
TestShapes window = new TestShapes();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(500,500);
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
for(Shape shape:shapes)
{
shape.printName();
shape.draw();
panel.add(shape);
}
window.add(panel);
window.setVisible(true);
}
public void paint (Graphics g)
{
super.paint(g);
}
}
You've not shown us your code for your Shape class and subclass, but regardless you're doing it wrong, and the fix is to not have them extend JComponent. Rather make them logical not component classes, and pass them into a JPanel that holds them in an ArrayList<...> and that draws them in its paintComponent method override. Then add this JPanel to your JFrame's contentPane, BorderLayout.CENTER, so that it may display its contained shapes.
Note that JComponents default to a preferred size of 0,0 unless they have been given other reason not to -- such as if they hold components that have preferred size or if they have an overridden getPreferredSize() method.
But again this is moot, because you're not wanting to display each figure in its own component as this will unnecessarily limit what you can do with the images and where you can display them.
I believe JViewport does work with JPanel, but when I build a new class that extends JPanel, it seem as if the JViewport is ignore by the program. I don't know if I do anything wrong, so this is the test I conduct and still get the same result:
public class panel extends JPanel
{
public panel()
{
super();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLUE);
g.drawString("Hello World", 50, 50);
g.setColor(Color.RED);
g.fillRect(50,50,100,100);
g.setColor(Color.BLACK);
g.fillOval(100, 100, 50, 50);
}
}
public class test extends JFrame
{
private panel p;
public void init()
{
this.setSize(1000, 1000);
this.setLayout(new BorderLayout());
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
p = new panel();
p.setOpaque(false);
JViewport v = new JViewport();
v.setViewSize(new Dimension(200,200));
v.setViewPosition(new Point(2000,2000));
v.setView(p);
this.add(v,BorderLayout.CENTER);
}
public test()
{
init();
}
public static void main(String[] args)
{
test t = new test();
}
}
It suppose to show part of the painted JPanel, but the JFrame window just display the whole JPanel. Therefore, I don't know if I did any wrong or JViewport is not built for this purpose. If it is the latter, then it would be great if anyone can suggest a workaround solution.
Thanks
The BorderLayout you're using is causing the viewport, which is placed in the center, to take the entire space inside the frame, since there are no other components in that layout. That's how the BorderLayout works.
Thus the viewport is also given a bigger size than defined (the size is overwritten by the layout manager). Since the panel doesn't have a fixed size either, it will also be resized.
In order to change that, either use a different layout manager or set a minimum/maximum size for the viewport and override getPreferredSize() for the panel.
As a side note: don't use lower case class names like panel.
I want to be able to Enter Text that will appear on the window and then if I were to re-size the window then the text could change with its size. The problem is that I'm not entirely sure how to implement this. Since I will to writing to the Jpanel I'm thinking I would have to use a Jlabel to add the text onto the window, but then resizing the window might not affect the Jlabel? Am I suppose to directly write on the Jpanel somehow, or get the size of the window(length and width) and use that to increase or decrease the size of the text? Any help would be appreciated.
If I understand your question correctly that you are trying to re-size some label type text you could try something along these lines:
public class ResizeTextTest extends JFrame{
public ResizeTextTest() {
add(new MyPanel());
}
public static void main(String[] args) {
ResizeTextTest t = new ResizeTextTest();
t.setSize(400,300);
t.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
t.setVisible(true);
}
class MyPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//Using a multiplier like this on the width and height of the
//Panel will give you a text size that correlates with the size
//of the window.
Font f = new Font("Arial", Font.PLAIN,
(int) (.0005 * this.getWidth() * this.getHeight()));
g.setFont(f);
g.drawString("Hello World", 50, 100);
}
}
The paintComponent method is automatically called when the window is resized. You can also call it explicitly using the component's repaint() method.
Use a text area, not a label. Make sure the 'line wrap' property is selected/true.
I am completely new to netbean's graphics system, and have been struggling with a java textbook. I am trying to produce a simple program to display some things, and have followed the book exactly as it wants me to. I found in my research a bunch of other people with a similar issues. These people tend to be told to use dimensions and preferredSize methods, though neither of these are mentioned in the section of the book I am trying to reproduce in java. The following is my code:
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
JFrame frame = new JFrame(); //create frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //makes x button end program
frame.setSize(300,200); //determine the size of the frame
ImageIcon image = new ImageIcon("panda.jpg");
ColorPanel p = new ColorPanel(Color.pink, image);
Container pane = frame.getContentPane();
pane.add(p);
frame.setVisible(true); //make frame show up
}
}
public class ColorPanel extends JPanel {
ImageIcon image;
public ColorPanel(Color c, ImageIcon i){
setBackground(c);
image = i;
}
#Override
public void paintComponents(Graphics g){
super.paintComponents(g);
setPreferredSize(new Dimension(100,100));
System.out.println("Blah!");
g.setColor(Color.blue);
g.drawRect(10,25,40,30);
}
}
I suppose there is a small typo in your code. You definitely mean to override paintComponent() and not paintComponents(). The first is called to paint the component, the second one to paint all components contained in your panel. Since there is none it will not be called.
These people tend to be told to use dimensions and preferredSize methods
You should not really use setPreferredSize(). Instead, you should override the getPreferredSize() method to return a proper value.
Also, you should never invoke setPreferredSize() in the paintComponent() method or change any property of the class in the paintComponent() method.