I have a board game (think Monopoly) where multiple game pieces can be located on a single tile. I got 4 circles drawn on a green background, but the circles are not centered and when I resize them the circles move all over the place instead of staying with the tile.
CirclePanel:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class CirclePanel extends JPanel {
public static final Dimension SIZE = new Dimension(35, 35);
public CirclePanel() {
}
#Override
protected void paintComponent(Graphics g) {
g.setColor(Color.RED);
g.fillOval(0, 0, 35, 35);
System.out.println(getSize());
}
#Override
public Dimension getPreferredSize() {
return SIZE;
}
}
GraphicsTile:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
#SuppressWarnings("serial")
public class GraphicsTile extends JPanel {
public static final Dimension SIZE = new Dimension(140, 140);
public static final GridLayout MGR = new GridLayout(2, 2);
public GraphicsTile() {
super();
setLayout(MGR);
add(new CirclePanel());
add(new CirclePanel());
add(new CirclePanel());
add(new CirclePanel());
}
#Override
public Dimension getPreferredSize() {
return SIZE;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(0, 0, 140, 140);
}
}
GraphicsRunner:
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
public class GraphicsRunner {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(4, 0, 5, 5));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1280, 720);
frame.setPreferredSize(new Dimension(140, 140));
frame.add(new GraphicsTile());
frame.add(new GraphicsTile());
frame.setVisible(true);
}
}
Once again, don't play with the size. All Swing components should determine their own preferred size. This includes panels and frame.
The panel will determine its size based on the component added to the panel.
The frame will determine its size based on the panels added to the frame. After the panels are added you use the pack() method.
Then all the components will be displayed at their preferred size. You could then just make the frame a fixed size by using:
frame.setResizable( false );
However, if you don't do the above then you need to determine what happens if the frame is resized. You then need to be more careful about the layout managers you use.
For a GridLayout all the components are resized to fill all the space available. This is easily verified by changing the painting code in your GraphicsTile` to:
//g.fillRect(0, 0, 140, 140);
g.fillRect(0, 0, getWidth(), getHeight());
This is the better painting technique. You should NOT be hardcoding values. Use properties of the component to specify the parameters when appropriate.
If you do this you will see the tiles expand to fill the area and the CirclePanel is at the beginning of the GraphicsTile (again because you hardcoded the location).
To prevent the GraphicsTile from expanding in size you will need to wrap it in another panel that respects the preferred size of the components added to it.
An easy way to do this is to use a GridBagLayout with the default GridBagConstraints. Now any component added to it will be centered in the space available.
So the restructuring of you main() method would look like:
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
JPanel tilePanel = new JPanel( new GridLayout(0, 1, 5, 5) );
tilePanel.add(new GraphicsTile());
tilePanel.add(new GraphicsTile());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(tilePanel, new GridBagConstraints());
frame.pack();
frame.setVisible(true);
It is because GridLayout automatically expand the content using the all the available space.
You could avoid this by wrapping your GraphicsTiles with another JPanel (which by default uses FlowLayout). This way the GridLayout would be forced to remain inside the wrapper.
For example in GraphicsRunner you could use panel as a wrapper:
JPanel panel = new JPanel();
panel.add(new GraphicsTile());
frame.add(panel);
panel = new JPanel();
panel.add(new GraphicsTile());
frame.add(panel);
But you might want to investigate if other layouts (or even not using layouts at all) suits your needs better.
Here a similar question that could help: How to set the component size with GridLayout? Is there a better way?
Related
I have a problem using BorderLayout, but first of all, here is my GUI setup:
As you can see, I have 3 different components inside my JFrame. Adding the JMenu and JList works fine. But my JPanel should have a fixed size so I want to prevent my BorderLayout from stretching the panel. I tried everything, setPreferredSize() setMinimumSize() setMaximumSize() setSize() but again the layout stretches my panel to fit to the frame. (The panel is added to the frame using BorderLayout.CENTER).
Is there any way to prevent this or do you have other suggestions to manage the problem?
I'm pretty sure you mean BorderLayout, not BoxLayout, because there is no BoxLayout.CENTER and it looks like you use a BorderLayout to place the components.
I think the problem here is that you only set the preferred size of the panel that you add to BorderLayout.CENTER. This doesn't have any effect. Instead you need nested layouts.
In this example I added the JPanel called centerPanel, which is using a standard GridBagLayout (to center the added component), to BorderLayout.CENTER. Then I added the additional JPanel called panel, which has a custom preferrdSize, to centerPanel. This way panel won't get stretched.
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
public class Example {
public Example() {
JMenuBar menuBar = new JMenuBar();
menuBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK));
DefaultListModel<String> listModel = new DefaultListModel<String>();
JList<String> list = new JList<String>(listModel);
list.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.BLACK));
JPanel panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
// Uncomment the following lines if you also want to prevent the
// 'wrapping' of the panel.
/*
* #Override public Dimension getMinimumSize() { return new
* Dimension(400, 400); }
*/
};
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
for (int i = 1; i <= 5; i++) {
menuBar.add(new JMenu("Menu " + i));
listModel.addElement("Element " + i);
panel.add(new JLabel("Label " + i));
}
JPanel centerPanel = new JPanel(new GridBagLayout());
centerPanel.add(panel);
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.add(menuBar, BorderLayout.NORTH);
contentPanel.add(list, BorderLayout.WEST);
contentPanel.add(centerPanel);
JFrame frame = new JFrame();
frame.setContentPane(contentPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
}
Add your existing JPanel to a JPanel having Flowlayout, the default, or having GridBagLayout with default constraints. Add this panel to the frame's center, BorderLayout.CENTER by default.
Panel centerPane = new Panel(new GridBagLayout())`;
centerPane.add(yourJPanel);
frame.add(centerPane, BorderLayout.CENTER);
Also consider using Box, rather than a JPanel having BoxLayout.
Also consider using the frame's setJMenuBar(), rather than add(BorderLayout.PAGE_START).
Attached is my window code:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import java.awt.BorderLayout;
import javax.swing.JTextPane;
public class Window extends JFrame{
private JPanel panel;
private JTextPane textPane;
private JTextPane textPane_1;
public Window() {
super("Window");
this.init();
this.setSize(800, 600);
this.setVisible(true);
}
void init(){
panel = new JPanel();
getContentPane().add(panel, BorderLayout.CENTER);
panel.setLayout(null);
textPane = new JTextPane();
textPane.setBounds(6, 48, 788, 185);
panel.add(textPane);
textPane.setFocusable(true);
textPane_1 = new JTextPane();
textPane_1.setBounds(6, 346, 788, 185);
panel.add(textPane_1);
JScrollPane scroll1 = new JScrollPane(textPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll1.setViewportView(textPane);
panel.add(scroll1);
this.add(scroll1);
JScrollPane scroll2 = new JScrollPane(textPane_1, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll2.setViewportView(textPane);
panel.add(scroll2);
this.add(scroll2);
this.add(panel);
}
}
My objective is for both JTextPanes to have their own scroll bars. All that appears on the screen though is a single JTextPane (not sure which one), and it has only a vertical scroll bar (I think this is because JTextPanes have word wrap). The second JTextPane isn't showing up. Can anyone help me?
Thanks in advance to all who reply.
You can use GridLayout in this case. See Swing Tutorial on How to Use GridLayout
Here is the code with GridLayout along with inline comments.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
public class MyWindow extends JFrame {
private JPanel panel;
private JTextPane textPane;
private JTextPane textPane_1;
public MyWindow() {
super("Window");
this.init();
}
void init() {
// panel with GridLayout having 2 rows and 1 column
panel = new JPanel(new GridLayout(2,1));
textPane = new JTextPane();
// enclose the text pane inside the scroll pane
// scroll pane shows scrollbars when needed
JScrollPane scroll1 = new JScrollPane(textPane);
// add scroll pane at first column of the first row
// never add text pane again in the panel because
// it's already added in scroll pane
panel.add(scroll1);
textPane_1 = new JTextPane();
JScrollPane scroll2 = new JScrollPane(textPane_1);
// add scroll pane at first column of the second row
panel.add(scroll2);
// finally add the panel in the JFrame's content pane in the center
getContentPane().add(panel, BorderLayout.CENTER);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
MyWindow window=new MyWindow();
window.setVisible(true);
}
});
}
}
snapshot:
Please have a look at Swing Tutorial on How to Use Various Layout Managers
Two points to start with, first, JFrame uses a BorderLayout by default, a BorderLayout only allows a single component to occupy any one of its five available positions. Second a component can only belong to a single parent
Taking a look at your code...
scroll1.setViewportView(textPane);
panel.add(scroll1);
this.add(scroll1);
//...
scroll2.setViewportView(textPane);
panel.add(scroll2);
this.add(scroll2);
this.add(panel);
You set textPane as the viewport view for scroll1
You add scroll1 to panel
You add scroll to this, effectively removing it from panel...
You set textPane as the viewport view of scroll2, removing it from the viewport for scroll1
You add scroll2 to the panel
You add scroll2 to this, effectively removing it from panel...
You add panel to this, overriding everything that was added to the frame previously...
This effectively means that panel is the only visible component the BorderLayout will try to layout on the frame, but it contains nothing
Instead, you could specify a position for each scroll pane when adding it to the frame, for example..
scroll1.setViewportView(textPane);
this.add(scroll1, BorderLayout.NORTH);
//...
scroll2.setViewportView(textPane_1);
this.add(scroll2, BorderLayout.SOUTH);
Updated with working example
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Window extends JFrame {
private JTextPane textPane;
private JTextPane textPane_1;
public Window() {
super("Window");
this.init();
this.setSize(800, 600);
this.setVisible(true);
}
void init() {
textPane = new JTextPane();
textPane_1 = new JTextPane();
JScrollPane scroll1 = new JScrollPane(textPane);
scroll1.setViewportView(textPane);
JScrollPane scroll2 = new JScrollPane(textPane_1);
add(scroll1, BorderLayout.NORTH);
add(scroll2, BorderLayout.SOUTH);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Window frame = new Window();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
This is the default behaviour for a JTextPane, it's overall size is determine by the size of it's content...
Now, you can make suggestions to the scrollpane about how much space your component would like to use by using the Scrollable interface and specifying the "initial", PreferredScrollableViewportSize...
Lucky for you, JTextPane already implements this interface, so you only need to override the getPreferredScrollableViewportSize method, for example...
textPane = new JTextPane() {
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
};
textPane_1 = new JTextPane() {
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
};
Take a look at Laying Out Components Within a Container for more details
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
This what I am doing but is nothing is getting displayed on Jframe window. I have not extended class JFrame to do my, is it necessary to do so for displaying objects on window.
public class testGraphics {
static JFrame workingFrame = null;
public static void main(String args[])
{
JFrame workingManager = new JFrame("Hello");
workingManager.setSize(500, 500);
workingManager.setVisible(true);
Graphics g = workingManager.getGraphics();
JPanel jp = (JPanel) workingManager.getContentPane();
workingManager.paintComponents(g);
g.fillOval(0, 0, 30, 30);
g.drawOval(0, 50, 30, 30);
g.setColor(Color.CYAN);
}
}
Do not ever call getGraphics() or explicitly call paintXxx() to do custom painting. The correct way to do custom painting is to override the paintComponent method of the panel to paint on. The overriden method will be implicitly called for you. Then add that panel to the frame. Also you should override the getPreferredSize() of the panel, so it has a preferred size, so you can just pack the frame
class PaintPanel extends JPanel {
#Override
protected paintComponent(Grapchics g) {
super.paintComponent(g);
g.drawString(....);
}
#Override
public Dimension getPreferredSize() {'
return new Dimension(300, 300);
}
}
Then add it to the frame (or if you want to set it as the content pane of the frame, do that instead)
PaintPanel panel = new PaintPaint();
frame.add(panel);
...
frame.pack();
See more at Performing Custom Painting
I made several changes to your code to get it to work properly.
I changed your main method to call the SwingUtilities invokeLater method to make sure that the Swing components were defined and used on the Event Dispatch thread.
I created a drawing JPanel. I set the color first, then drew the ovals.
I added a JFrame default close operation. You must specify a default close operation, or else your Java application will continue running after you close the JFrame.
I moved the size to the drawing panel. The frame size will be calculated when you call the JFrame pack method.
And here's the modified code:
package com.ggl.testing;
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.SwingUtilities;
public class TestGraphics implements Runnable{
private JFrame workingManager;
private JPanel drawingPanel;
#Override
public void run() {
workingManager = new JFrame("Hello");
workingManager.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
drawingPanel = new DrawingPanel();
workingManager.add(drawingPanel, BorderLayout.CENTER);
workingManager.pack();
workingManager.setLocationByPlatform(true);
workingManager.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new TestGraphics());
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID =
-3701718376300985046L;
public DrawingPanel() {
this.setPreferredSize(new Dimension(500, 500));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.CYAN);
g.fillOval(0, 0, 30, 30);
g.drawOval(0, 50, 30, 30);
}
}
}
The setSize() and setVisible() must be at the bottom of the method:
JFrame workingManager = new JFrame("Hello");
Graphics g = workingManager.getGraphics();
JPanel jp = (JPanel) workingManager.getContentPane();
workingManager.paintComponents(g);
g.fillOval(0, 0, 30, 30);
g.drawOval(0, 50, 30, 30);
g.setColor(Color.CYAN);
workingManager.setSize(500, 500);
workingManager.setVisible(true);
I'm making a GUI for a a custom source server browser with improved filtering.
This is what I have so far.
However, when I resize...
When I resize the window I want the L4D2 'filter panel' to resize to the current maximum width of the container. I also want to be able to add more of these panels in a column (such as box layout provides).
Boxlayout get's the panels to appear in a column, but it doesn't do anything for their widths.
I'm thinking I may need to override the filter panels preferred size methods so that they can retrieve the size of the parent container, but I'm not sure how to do this.
How should I approach this problem?
EDIT: Here's an example program depicting the problem.
import javax.swing.*;
import java.awt.*;
public class guiExampleProblem {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final MyWindows wnd = new MyWindows("guiExampleProblem");
wnd.setVisible(true);
}
});
}
}
class MyWindows extends JFrame {
public MyWindows(String text) {
super(text);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
JPanel containerPanel1 = new JPanel();
JPanel containerPanel2 = new JPanel();
JPanel containerPanel3 = new JPanel();
containerPanel1.setBackground(Color.BLACK);
containerPanel2.setBackground(Color.RED);
containerPanel3.setBackground(Color.GREEN);
mainPanel.add(containerPanel1);
mainPanel.add(containerPanel2);
mainPanel.add(containerPanel3);
this.add(mainPanel);
pack();
}
}
When the window is resized, I want the panels to expand only along the x-axis, and remain at a constant height on the y-axis, however in the example the panels expand on both the x y axis.
I managed to get the desired functionality by overriding the 'filter panels' getPrefferedSize methods so that they retrieve the parent containers width and use that. Here is the code in the form of an example:
import javax.swing.*;
import java.awt.*;
public class guiExampleProblem {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final MyWindows wnd = new MyWindows("guiExampleProblem");
wnd.setVisible(true);
}
});
}
}
class MyWindows extends JFrame {
public MyWindows(String text) {
super(text);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new FlowLayout());
JPanel containerPanel1 = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(this.getParent().getWidth(),60);
}
};
JPanel containerPanel2 = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(this.getParent().getWidth(),60);
}
};
JPanel containerPanel3 = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(this.getParent().getWidth(),60);
}
};
containerPanel1.setBackground(Color.BLACK);
containerPanel2.setBackground(Color.RED);
containerPanel3.setBackground(Color.GREEN);
mainPanel.add(containerPanel1);
mainPanel.add(containerPanel2);
mainPanel.add(containerPanel3);
this.add(mainPanel);
pack();
}
}
Put the panel (with BoxLayout) that is to stretch in the CENTER of a BorderLayout -- put the panel to the right in the EAST of that BorderLayout. You have given no detail of what else you want this to do, nor any code, but this might be what you want.
--
After your solution: it seems to me that using FlowLayout here is confusing -- it lays out its components one after the other horizontally, and your trick of getting preferred size from the width of the container makes it behave differently. I also avoid getting into layout logic in my application when I can, so I looked for another way to do this and came up with:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class guiExampleProblem2
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
final MyWindows2 wnd = new MyWindows2("guiExampleProblem2");
wnd.setVisible(true);
}
});
}
}
class MyWindows2 extends JFrame
{
public MyWindows2(String text)
{
super(text);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
JPanel containerPanel1 = addContainedPanel(Color.BLACK, 60, 60, mainPanel);
JPanel containerPanel2 = addContainedPanel(Color.RED, 60, 60, mainPanel);
JPanel containerPanel3 = addContainedPanel(Color.GREEN, 60, 60, mainPanel);
this.add(mainPanel, BorderLayout.NORTH);
pack();
}
JPanel addContainedPanel(Color color, int width, int height, JPanel container)
{
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(width, height));
panel.setBackground(color);
container.add(panel);
return panel;
}
}
This uses the NORTH portion of a BorderLayout (which is the default layout for a JFrame, by the way) to do the main thing you wanted -- stretch things horizontally. The BoxLayout with a page axis is intended to lay things out top-to-bottom, so I think that's less confusing for the reader. Anyway, it's another way to do it that I think uses the components - including the layout managers - more like they were intended and documented.
Hi all im trying to do is add a button to the screen, so when the user clicks on the button a random dice picture is displayed somewhere else on the screen.
Simple
this is my code how I've tried doing it...
although i cant seem to get the buttons to appear with the picture. its either one or the other. what am i doing wrong?
Any help would be appreciated.
also im sure im using far too much code just to get the desired output.
ava.util.Random;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
class MyComponent extends JComponent {
public void paint(Graphics g) {
ImageIcon icon = new ImageIcon("dice1.png");
int x = 0;
int y = 0;
icon.paintIcon(this, g, x, y);
}
}
class Dice extends Panel
{
BufferedImage image;
public Dice(){
JFrame frame = new JFrame("Test");
JPanel panel = new JPanel();
frame.add(panel);
JButton button2 = new JButton("Roll Die");
button2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
//execute when button is pressed
Random r= new Random();
System.out.println(r.nextInt(6)+1);
}
});
panel.add(button2);
frame.add(new MyComponent());
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
}
public void paint(Graphics g){
g.drawImage(image, 0, 0, 50,50, null);
}
public static void main(String[] args)
{
Random r= new Random();
System.out.println(r.nextInt(6)+1);
new Dice();
}
}
The issue is that the JFrame's contentPane has a BorderLayout by default and BorderLayout adds components to it's CENTER area by default. BorderLayout only supports one component in each of it's regions so when you add both yourJPanel and your custom component to the frame, only one is acutally displayed. The solution is to set the JFrame's contentPane to use another layout(FlowLayout maybe?):
frame.getContentPane().setLayout(new FlowLayout());
or to add one fo the components to another region of the BorderLayout:
frame.getContentPane.add(new MyComponent(), BorderLayout.West);