I'm trying to add an ImageIcon to a panel through paintComponent, but it doesn't work. The panel i'm trying to add it to is set to a GridLayout. Could this be why? or is it being drawn over? Or my path could be set incorrectly... I've never
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Frame implements MouseListener, KeyListener {
JFrame f = new JFrame();
JPanel p = new JPanel();
JPanel[][] panel = new JPanel[10][10];
int k = 1;
Color previous;
ImageIcon icon = new ImageIcon("/Users/Admin/Desktop/stickFigure.jpg");
static String title = "Grid World";
public Frame(String s) {
f.setTitle(s);
p.setLayout(new GridLayout(10, 10));
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
panel[i][j] = new JPanel();
p.add(panel[i][j], i, j);
panel[i][j].addMouseListener(this);
panel[i][j].setBackground(Color.WHITE);
}
}
p.setSize(500, 500);
f.add(p);
f.setSize(490, 492);
f.setVisible(true);
f.setResizable(false);
f.setDefaultCloseOperation(3);
f.addKeyListener(this);
f.setLocationRelativeTo(null);
}
public void paintComponent(Graphics g) {
icon.paintIcon(f, g, 100, 100);
}
You've got a paintComponent method in a class that does not extend JPanel, JComponent or any similar object, and thus it will never be called and serve no purpose. If you want paintComponent to work as intended, it must be in a class that extends JComponent or one of its children such as JPanel. And then you must use that JPanel in your GUI. Please read the Swing painting tutorials to see how to do this correctly.
Edit
Another way to display an ImageIcon is to simply add it to a JLabel and then display the JLabel in a Swing GUI.
Edit 2
Also, even if your class extended JPanel, it still wouldn't work since your icon is never added to anything. I've not seen graphics done as you're doing -- by calling the icon's paintIcon(...) method. I can't say that it's wrong; just that I haven't seen done this way.
Related
I am making a custom JComponent to my Swing GUI.
public class BreadCrump extends JComponent implements MouseListener,
MouseMotionListener{
JPanel cajaPrincipal;
JLabel nombre;
JLabel propiedadUsada;
JLabel numeroApariciones; //OPCIONAL
public BreadCrump(String nombre, String relacion)
{
}
public BreadCrump(String nombre)
{
this.nombre = new JLabel(nombre);
this.cajaPrincipal = new JPanel();
this.cajaPrincipal.setPreferredSize(new Dimension(60,40));
this.cajaPrincipal.setSize(60, 40);
this.cajaPrincipal.add(this.nombre);
this.cajaPrincipal.setBackground(Color.blue);
this.nombre.setLocation(10, 10);
this.cajaPrincipal.setVisible(true);
this.setPreferredSize(new Dimension(60,40));
this.setSize(60,40);
this.setBackground(Color.red);
this.setVisible(true);
addMouseListener(this);
addMouseMotionListener(this);
}
And create the objects in this fragment of code:
JPanel a = new JPanel();
JScrollPane sp = new JScrollPane(a);
sp.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
sp.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
//sp.setBounds(0, 0,father.getSize().width, height);
this.add(sp);
father.add(this, java.awt.BorderLayout.PAGE_END);
for (int i = 0; i < 8; i++) {
BreadCrump prueba = new BreadCrump("prueba " + i);
a.add(prueba);
}
The problem is that I cant see the component. The component exists an is inside my JPanel 'a' and the JScrollPane detect it because the scroll bar appears.
I tried to change JComponent to JPanel and it works, i can see the JPanel(when I change the color and the preferredSize). But I dont know why can not see my JComponent.
Anyone knows what I am doing wrong? Maybe I need put a location to the component? I tried to add size and visible but nothing occurs.
Thanks for your time!
My main issue is with the following piece of code when setting up a JFrame:
Why the panel doesn't show if I use the pack() and how to make it work?
Why the first requestFocusInWindow() doesn't work and what the principle to use it?
Why the default layout manager of JPanel doesn't work if I delete the setLayout()?
public class SoundGUI extends KeyAdapter{
public static void main(String[] args) {
SoundGUI sGUI = new SoundGUI();
sGUI.setUp();
}
public void setUp () {
JFrame frame = new JFrame ("Key test");
frame.setSize (1000, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible (true);
Panel p = new Panel ();
p.setLayout(new BorderLayout());//why this sentence is necessary FlowLayout doesn't fill the container but rather lets components size to their preferredSizes.
p.addKeyListener (this);
p.requestFocusInWindow();//it's useless here
//requestFocus only works on focusable components that are displayed.
MyDrawPanel dp = new MyDrawPanel();
dp.setBackground(Color.darkGray);
JLabel test = new JLabel("a trial");
JButton t = new JButton("b");
dp.add(t);
dp.add (test);
p.add (dp);
frame.getContentPane().add(p);
p.requestFocusInWindow();
//frame.pack();//why it doesn't work
//frame.setVisible(true);
}
class MyDrawPanel extends JPanel {
public void paintComponent (Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.white);
for (int i = 0; i < 1000; i += 42) {
g2.fill3DRect(i,100 ,20 ,80 ,true);
}
g2.setColor(Color.black);
for (int i = 21; i < 1000; i += 42) {
g2.fill3DRect(i,100 ,20 ,80 ,true);
}
}
}
}
Suggestions:
Call setVisible(true) after calling pack(). Makes sense, doesn't it?
The BorderLayout will tell the MyDrawPanel to fill the p container, since the component is being added in a default way (meaning BorderLayout.CENTER), and that's how BorderLayout works.
FlowLayout doesn't fill the container but rather lets components size to their preferredSizes.
Don't mix Swing with AWT components. i.e., don't use Panels, but rather use JPanels.
requestFocus only works on focusable components that are displayed.
Better to use Key Bindings than KeyListeners.
Better to avoid setting the sizes of anything if possible.
Based on your new code, your problem is due to you're calling setSize(). Most layout managers don't respect this but rather the preferred size. If your drawing JPanel needs to be so big, then make it so. For example try:
class MyDrawPanel extends JPanel {
private static final int PREF_W = 1000;
private static final int PREF_H = 300;
public void paintComponent(Graphics g) {
super.paintComponent(g); //!! ******** don't forget this!!! *********
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.white);
for (int i = 0; i < 1000; i += 42) {
g2.fill3DRect(i, 100, 20, 80, true);
}
g2.setColor(Color.black);
for (int i = 21; i < 1000; i += 42) {
g2.fill3DRect(i, 100, 20, 80, true);
}
}
// the getPReferredSize will make this JPanel preferentially be this size
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
}
Also note that request focus does work if the component is focusable:
JPanel p = new JPanel(); //!! This should be a JPanel, not a Panel
p.setFocusable(true); //!! This is needed
p.setLayout(new BorderLayout());
p.addKeyListener(this);
p.requestFocusInWindow();
But also note that KeyListeners should be avoided. Use Key Bindings instead.
I have a Gui I'm making for a program that has an outer container centered to the JFrame that contains an inner container that holds 22*12 cells. When I run this program, the background just flickers white and stays like that. If you could point me out where I'm going wrong that would be awesome!
public class Gui extends JFrame
{
private JPanel outer, inner;
private JLabel[][] labels = new JLabel[22][12];
public Gui()
{
setBackground(Color.black);
setSize(1000,1000);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
outer = new JPanel();
outer.setLayout(new BorderLayout());
outer.setSize(620,920);
outer.setBackground(Color.white);
inner = new JPanel();
inner.setLayout(new GridLayout(22,12,10,10));
inner.setSize(600,900);
inner.setBackground(Color.white);
for (int i = 0; i < 22; i++)
{
for (int j = 0; j < 12; j++)
{
labels[i][j] = new JLabel();
JLabel label = labels[i][j];
label.setSize(50,50);
label.setBackground(Color.gray);
inner.add(label);
}
}
outer.add(inner, BorderLayout.CENTER);
add(outer, BorderLayout.CENTER);
}
}
The gui is set visible in the main class that instantiates it.
The gui is created and sized correctly. It starts out with a black background then randomly turns to white just after and stays like that.
EDIT: if this is still important:
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Gui gui = new Gui();
gui.setVisible(true);
}
});
}
Use the new static variable names which follow final static naming convention. That is the variable should be upper cased:
//setBackground(Color.black);
setBackground(Color.BLACK);
Don't use setSize() for components. Instead add the components to the frame and then use the pack() method so the components are displayed at their preferred size:
//setSize(1000,1000);
add(component1);
add(anotherComponent);
pack();
Layout managers use the preferred size not the size as a layout tip:
//label.setSize(50,50);
label.setPreferredSize(new Dimension(50, 50));
This is your main problem. A JLabel is transparent by default, so the background color you set is ignored:
label.setBackground(Color.gray);
label.setOpaque(true);
By the way, my screen height is only 738, so won't event be able to see you entire frame since you want a height of 22*50. You should be aware of this and probably add your panel to a JScrollPane so people like me can actually use your application. This is why you should not hardcode a preferred size.
I have a poker game where I designed a nice pretty GUI that displays the cards and players. I did it all extending JPanel inside paint() with a lot of g2d.drawImage's and g2d.drawString()'s, with definite x and y locations.
My problem now is that I need to have a couple interactive buttons underneath it.. but whenever I try to add a JButton, it appears top and center. I've used setLocation(x, y) and setLayout(null) and everything I've seen in other replies, but none of them seem to match my need (Or at least I don't have a very well understanding of where to put it)
This is how my code is set up:
pokerserver.java
public class pokerserver extends JFrame {
public pokerserver() {
add(new drawing());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(720, 640);
setLocationRelativeTo(null);
setTitle("Poker HANGOUTS");
setResizable(false);
setVisible(true);
}
public static void main(String args[]) {
new pokerserver();
}
And then in drawing.class
public drawing() {
setFocusable(true);
setBackground(new Color(39,91,46));
setDoubleBuffered(true);
gameCards = new cards();
gameCards.shuffle();
for (int i = 0; i < 10; i++)
seats[i] = -1;
HQ = new HeadQuarters(this);
HQ.start();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
//All my UI code
}
My last attempt was trying to add
JButton button = new JButton("TEST");
add(button);
button.setLocation(10, 500);
at the end of public drawing(). I Keep seeing things on layout management, but it's not helping me -- mainly because I'm not sure how to implement it
Here's a screenshot to help visualize what I'm talking about->
http://i.imgur.com/ttvif.png
Trying to get the button underneath. Unless there's a way to add an ActionListener to a drawImage()?
For your main panel use a BorderLayout.
Then to the "CENTER" you can add your game panel with all your custom painting.
Then create a panel and add the buttons to it. Now you can add this panel to the NORTH of the main panel.
In other words you are not restricted to using a single panel.
Also, custom painting should be done in the paintComponent() method of your panel, NOT the paint() method.
I'm not really sure what you are after, but here are two interpretations.
I suspect you want the 1st one 'Buttons over custom painting', but as a user I'd prefer the 2nd, with 'Buttons below custom painting'.
import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
class PaintPanel extends JPanel {
BufferedImage bg;
PaintPanel(LayoutManager2 layout) {
super(layout);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (bg==null) {
bg = new BufferedImage(500,500,BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bg.createGraphics();
GradientPaint gp = new GradientPaint(
0,0,Color.RED,500,500,Color.BLUE);
g2.setPaint(gp);
g2.fillRect(0,0,500,500);
g2.dispose();
}
g.drawImage(bg,0,0,getWidth(),getHeight(),this);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel buttons = new JPanel(
new FlowLayout(FlowLayout.CENTER));
buttons.setOpaque(false);
buttons.add(new JButton("Start"));
buttons.add(new JButton("Stop"));
PaintPanel pp = new PaintPanel(new BorderLayout());
pp.setPreferredSize(new Dimension(200,100));
pp.add(buttons, BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null,pp);
JPanel gui = new JPanel(new BorderLayout());
gui.setBackground(Color.ORANGE);
gui.add(pp, BorderLayout.CENTER);
gui.add(buttons, BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null,gui);
}
});
}
}
Why my JFrame 'frame' is diplaying empty window, when it should give me 3 menu buttons and my own painted JComponent below ? What am I missing here ?
import java.awt.*;
import javax.swing.*;
public class Eyes extends JFrame {
public static void main(String[] args) {
final JFrame frame = new JFrame("Eyes");
frame.setPreferredSize(new Dimension(450, 300));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel players = new JPanel(new GridLayout(1, 3));
players.add(new JButton("Eyes color"));
players.add(new JButton("Eye pupil"));
players.add(new JButton("Background color"));
JPanel eyes = new JPanel();
eyes.add(new MyComponent());
JPanel content = new JPanel();
content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
content.add(players);
content.add(eyes);
frame.getContentPane();
frame.pack();
frame.setVisible(true);
}
}
class MyComponent extends JComponent {
public MyComponent(){
}
#Override
public void paint(Graphics g) {
int height = 120;
int width = 120;
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
BasicStroke bs = new BasicStroke(3.0f);
g2d.setStroke(bs);
g2d.setColor(Color.yellow);
g2d.fillOval(200, 200, height, width);
g2d.setColor(Color.black);
g2d.drawOval(60, 60, height, width);
}
}
Your line:
frame.getContentPane();
doesnt do anything but access the content pane of the frame. Instead of getting the content pane, you should set your content pane, like this:
frame.setContentPane(content);
EDIT:
alternatively, as #trashgod points out, you could use the getContentPane method to access the default content pane and add your content component to that:
frame.getContentPane().add(content);
I think you are attempting to use nested JPanels. This is certainly a way to organize your components, but downside to is the fact that it gets difficult to manage in some cases. You could try this snippet of code below. In the program you will find:
1) An array of JLabel
2) An array of JTextField
3) Nested JPanels
At the end of the program I use the Container to add the final product of these object to my Graphics Window.
The most efficient way I can think of is to define these components at the top of my program so that I can reuse them later as I need to.
To achieve this you can try this snippet of code:
import javax.swing.*; //Required to use Swing Components
public class TestGUI extends JFrame
{
JLabel[] label; //Define this with an array
JTextField[] textField; //Define this with an array as well
private int nLabels; //Number of labels preferred
private int nTextFields; //Number of text fields preferred
public testGUI(int amt)
{
//Assuming that you want equal amounts of each,
//set these two variables to the "ant" input parameter
nLabels = amt;
nTextFields = amt;
//Set component attributes
label = new JLabel[2]; //Label compared text fields
textField = new JTextField[2]; //Use two of these for comparison
textField[0].setEnabled(false); //Disabled editing
//Do nothing with the second text field
JPanel labels = new JPanel(); //Place JLabels here
//Use this to align the labels vertically
labels.setLayout(new GridLayout(2, 1));
//Use this for loop to add the labels to this JPanel
for(int i = 0; i < nLabels; i++)
{
labels.add(label[i]);
//You can also define and apply additional properties
//to labels inside this loop. TIP: You can do this in
//any loop
}
JPanel txtFields = new JPanel(); //Place JTextFields here
//Use this to align the text fields vertically
txtFields.setLayout(new GridLayout(2, 1));
//Use this for loop to add the labels to this JPanel
for(int i = 0; i < nTextFields; i++)
{
textFields.add(textField[i]);
//You can also define and apply additional properties
//to text fields inside this loop. TIP: You can do
//this in any loop
}
//Now we have the two components, you asked for help with, set up
//Next, we will need another JPanel to add these to panels to.
//This JPanel will be added to the JFrame Container
//You probably know how to run this via the "main" method
JPanel window = new JPanel();
//Place the JPanel for the labels and text fields
//This requires a horizontal grid
window.setLayout(new GridLayout(1, 2));
//Add the the two JPanels: "labels" and "txtFields"
window.add(labels);
window.add(txtFields);
//Define the Container object to set up the GUI
Container container = getContentPane();
//Apply the "window" JPanel object to the container
container.add(window, BorderLayout.CENTER);
//Center this in the Graphics Window when displayed
}
//Any other methods and/or functions can be added as well
//If they are, they must placed in the constructor method above
}
This is the approach that I would use when trying to go at making and manipulating my Graphics Windows that I write. Sometimes I write applets, but only after making sure that I have everything functioning properly in a plain Graphics Window.
I hope this helps.
If you have any other questions, just let me know and I will answer the to the best of my ability, thanks.