I have looked online, but I am still having trouble understanding how to add graphics to a JPanel
Here is the code for my panel class:
public class GamePanel extends JPanel {
public GamePanel(){
}
public void paintComponent(Graphics g) {
g.drawString("asd", 5, 5);
}
}
And my main method:
public static void main(String[] args) {
frame.setLayout(new FlowLayout());
frame.getContentPane().setBackground(Color.WHITE);
//i is an instance of GamePanel
frame.add(i);
frame.setPreferredSize(new Dimension(500, 500));
frame.pack();
frame.setVisible(true);
}
Text will only appear in a very tiny section of the screen (this applies to any graphics object I try to draw). What am I doing wrong?
FlowLayout respects preferred sizes of components. Therefore override getPreferredSize to give your JPanel a visible size rather than the default zero size Dimension that the panel currently has after JFrame#pack is called:
class GamePanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g); // added to paint child components
g.drawString("asd", 5, 20);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 300);
}
}
Edit:
To eliminate gap between JPanel and its containing JFrame, set the vertical gap to 0:
frame.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
Two things jump out
Your Game panel has no preferred size, which, by default, makes 0x0. FlowLayout will use this information to make decisions about how best to layout your panel. Because the size is 0x0, the repaint manager will ignore it. Try overriding the getPreferredSize method and return a appropriate size or use a layout manager that does not use the preferred size, like BorderLayout
Your paintComponent method MUST call super.paintComponet
Related
Why is paintComponent(Graphics) not called when adding a custom JComponent?
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame("Paint Component Example");
frame.setPreferredSize(new Dimension(750, 750));
frame.setLocationByPlatform(true);
JPanel panel = new JPanel();
panel.add(new CustomComponent());
frame.add(panel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
public class CustomComponent extends JComponent {
public CustomComponent() {
super();
}
#Override
protected void paintComponent(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(10, 10, 10, 10);
}
}
I know there is no reason for creating a custom component in this instance of but it is an extremely simplified version of another issue I can't figure out.
JPanel panel = new JPanel();
panel.add(new CustomComponent());
The default layout manager of a JPanel is a FlowLayout. A FlowLayout will respect the preferred size of any component added to it. By default the preferred size of a JComponent is (0, 0) so there is nothing to paint so the paintComponent() method never gets called.
Override the getPreferredSize() method of your CustomComponent class to return the preferred size of your component.
Also, don't forget to invoke super.paintComponent(...) at the start of the method.
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
I am making an adaptation of a board game. The board will be drawn on a JPanel by overriding the paintComponent(Graphics g) method. The board can possibly be larger than the size of the JPanel it is drawn in, so I planned to use a JScrollPane to allow the user to scroll across the board to view it. As an example, I made the board a single large rectangle to see if I could get it to scroll across that, but to no avail. I have used JScrollPane successfully before but I cannot figure out why this case is any different from the way I previously used it.
Can anyone see why it is not working correctly?
Here is the code for the Game's JFrame:
public class GameFrame extends JFrame{
JPanel playerDeckPanel, contentPane;
JScrollPane gameScrollPane;
BoardPanel boardPanel;
public GameFrame(){
super();
SwingUtilities.invokeLater(new Runnable(){
public void run(){
boardPanel = new BoardPanel();
playerDeckPanel = new JPanel();
boardPanel.setLayout(new GridLayout(1,1));
playerDeckPanel.setLayout(new CardLayout());
boardPanel.setSize(1000,1000);
gameScrollPane = new JScrollPane(boardPanel);
gameScrollPane.setPreferredSize(new Dimension(300,300));
contentPane = ((JPanel) getContentPane());
contentPane.setLayout(new GridLayout(1,2));
contentPane.add(gameScrollPane);
contentPane.add(playerDeckPanel);
setMinimumSize(new Dimension(800,600));
}
});
}
public static void main(String[] args){
GameFrame gameFrame = new GameFrame();
gameFrame.setVisible(true);
}
private class BoardPanel extends JPanel{
public BoardPanel(){
super();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(100, 10, 700, 600);
revalidate();
}
}
}
This is my first time posting a question, so let me know if you need additional information to solve this problem
You need to setPreferredSize on BoardPanel, that seems to do the trick. Don't ask why ;-)
-#geert3
Try to draw a rectangle with different size, How to fit it in one frame proportionally(assume the frame is fixed)?
public class Draw extends JComponent {
public void paint(Graphics g) {
int width = 100;
int length = 100;
g.drawRect(10, 10, width, length);
}
}
public class DrawRect {
public static void main(String[] a) {
JFrame frame = new JFrame();
frame.setSize(400, 600));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Container content = frame.getContentPane();
content.add(new Draw());
}
}
Custom painting is done by overriding the paintComponent(...) method, not the paint() method. This advice is made daily. Search the forum for more information and examples.
If you want to know the space available to the component then you can invoke the getWidth() and getHeight() method. Once you know these values you can determine how big you want to paint your rectangle.
Components should be added to the frame BEFORE the frame is made visible.
You don't need to use the getContentPane() method. Since JDK5 you can just add components directly to the frame and they will be added to the content pane for you.
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 have no idea why I can't find a solution for this... I am trying to layout some AWT components in a flow layout. The only problem is the 'padding' between the components (Panels) when using a flow layout. This is what the applet currently looks like: http://i.stack.imgur.com/2KZgD.png
I need a way to set the Applet/Panels so that the two panels (black boxes) are touching (no 'padding'). The entire program is Swing free, all AWT, and I plan on keeping it that way. I feel this is a very simple solution, but I have not been able to find an answer.
This is the init() code from the applet class:
public void init() {
setLayout(new FlowLayout());
c1 = new TestPanel();
c2 = new TestPanel();
c1.setPreferredSize(new Dimension(640, 480));
c2.setPreferredSize(new Dimension(100, 480));
add(c1);
add(c2);
}
This is the TestPanel class I'm using:
public class TestPanel extends Panel {
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, this.getPreferredSize().width, this.getPreferredSize().height);
}
}
The default horizontal (and vertical) gap of FlowLayout is set to 5. Therefore, you must explicitly set the horizontal gap to 0.
FIRST APPROACH
Invoke setHgap(...) on the component's layout. Since the default layout of a JPanel is FlowLayout, simply do the following:
((FlowLayout)getLayout()).setHgap(0);
SECOND APPROACH
Use another FlowLayout constructor. That is, FlowLayout(int align, int hgap, int vgap). And simply do the following:
setLayout(new FlowLayout(FlowLayout.CENTER, 0, 5));