I have created a KeyAdapter class within my JPanel class, and I tried debugging the click using System.out.println(String par1);
However it doesnt seem to work...
Here is the class:
package net.ryanshah;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class Menu extends JPanel
{
private GameFrame gf;
private Image bg = new ImageIcon("res/bg.png").getImage();
public Menu(final GameFrame parent) {
this.gf = parent;
int width = parent.getWidth();
int height = parent.getHeight();
setFocusable(true);
addKeyListener(new MenuOperator());
setBackground(Color.black);
setLayout(null);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int w = getWidth();
int h = getHeight();
g2d.drawImage(bg, 0, 0, null);
}
public class MenuOperator extends KeyAdapter {
#Override
public void keyPressed(KeyEvent event) {
int keyCode = event.getKeyCode();
if(keyCode == KeyEvent.VK_SPACE) {
System.out.println("LOL");
}
}
}
}
Does anyone know what the problem might be? I have set the key handler in the frame as well as setting the frame to be focusable..
Thanks in advance
~RyanS.
Things not considered right in the code (IMHO) :
The way you accessing the images in your code. Consider ImageIO, over using the constructor of ImageIcon, as the former will notify you, in case something goes wrong. For more info, please refer, Loading Image Icon Exception, for more insight.
KeyListeners are for AWT, Swing on the other hand uses KeyBindings.
Before, setting background on any JComponent prefer to first set the opaque property of the said JComponent to true. Since, opaque property is usually dependent on LookAndFeel used.
Avoid the use of setLayout(null), as much as possible. Please walk through the first paragraph of Absolute Positioning for more information :-)
THe use of ImageObserver as already mentioned in the comments.
This blog Motion Using the Keyboard by #camickr, will again add loads to your knowledge, as to why KeyListeners are not considered a better option and why KeyBindings is more suited for such needs :-)
Please have a look at this example :
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class TestMenu extends JPanel {
private Image bg;
public TestMenu() {
try {
bg = ImageIO.read(
new URL("http://i.imgur.com/Aoluk8n.gif"));
} catch (Exception e) {
e.printStackTrace();
}
getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "SPACE key");
getActionMap().put("SPACE key", keyAction);
setOpaque(true);
setBackground(Color.black);
}
private Action keyAction = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
System.out.println("LOL");
}
};
/*
* Make this a customary habbit to override
* this method for the JPanel/JComponent,
* when ever you extend any of the above classes
*/
#Override
public Dimension getPreferredSize() {
return (new Dimension(200, 200));
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int w = getWidth();
int h = getHeight();
/*
* Here the last part of the drawImage is the
* ImageObserver, here it is a good practise
* to keep the instance of the JPanel on which
* we drawing the image to be notified, till the
* end, till the image loading is not complete
*/
g2d.drawImage(bg, 0, 0, this);
}
private void displayGUI() {
JFrame frame = new JFrame("Painting Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setContentPane(this);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
new TestMenu().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
}
Setting your panel focusable is not enough - panel cannot get focus on its own - you have to request the focus on some kind of event. For example you can add a mouse listener to your panel and call panel.requestFocusInWindow() when you click on it.
Key listener will work only if component on which you add it has focus.
Related
I started programming in SWING class recently and I try to set Image (like Space) and on it image(like spaceShip) like background. I
would love for you to help me,
Here is my code
public class SpaceWar {
static JFrame frame = new JFrame("Space War");
static JPanel panel = new JPanel();
public static void main(String[] args) {
new SpaceWar();
//frame.setResizable(false);
frame.setVisible(true);
}
public SpaceWar() {
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
Dimension size
= Toolkit.getDefaultToolkit().getScreenSize();
frame.setPreferredSize(size);
frame.setLayout(null);
panel.setLayout(null);
panel.setBounds(frame.getPreferredSize().width/4,0,
frame.getPreferredSize().width/2,frame.getPreferredSize().height);
frame.add(panel);
frame.add(new Background());
spaceShip sp1 = new spaceShip();
panel.setBackground(Color.black);
panel.add(sp1);
System.out.println(panel.getPreferredSize().width);
}
}
class spaceShip extends JLabel{
static ImageIcon img = new ImageIcon("spaceShip.png");
public spaceShip(){
sizeIcon(100,100,img);
setIcon(img);
}
public static ImageIcon sizeIcon(int w,int h,ImageIcon image1){
Image image = image1.getImage(); // transform it
Image newimg = image.getScaledInstance(w,h, java.awt.Image.SCALE_SMOOTH); // scale it the smooth way
ImageIcon img1 = new ImageIcon(newimg); // transform it back
return img1;
}
}
class Background extends JPanel{
public void paint(Graphics g) { // paint() method
super.paint(g);
ImageIcon image = new ImageIcon("space.jpg");
Image bg = image.getImage();
g.drawImage(bg,0,0,null);
}
}
So, your "core" problem is the use of null layouts and a lack of understand of how components are sized and positioned. Having said that, if your aim is to make a game, this probably isn't the best approach anyway.
Instead, I'd focus on creating a "surface", onto which you can paint all your assets directly, this will give you much greater control.
Start by taking a look at Painting in AWT and Swing and Performing Custom Painting to get a better understanding how the paint system works and how you can work with it to perform custom painting.
I'd also avoid ImageIcon, it's not the best way to handle images, instead, take a look at ImageIO (Reading/Loading an Image), it will generate an IOException if the image can't be loaded and will return a fully realised image (unlike ImageIcon which off loads the image loading to a background thread).
For example...
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public class MainPane extends JPanel {
private BufferedImage ufo;
private BufferedImage background;
private int horizontalPosition = 106;
public MainPane() throws IOException {
ufo = ImageIO.read(getClass().getResource("/images/ufo.png"));
background = ImageIO.read(getClass().getResource("/images/starfield.png"));
System.out.println("background = " + background);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
paintBackground(g2d);
paintUFO(g2d);
g2d.dispose();
}
protected void paintBackground(Graphics2D g2d) {
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g2d.drawImage(background, x, y, this);
}
protected void paintUFO(Graphics2D g2d) {
int x = (getWidth() - ufo.getWidth()) / 2;
int y = (getHeight() - ufo.getHeight()) / 2;
g2d.drawImage(ufo, x, y, this);
}
}
}
The example makes use of embedded resources (something to read up on). Managing your assets this way will save you countless hours of wondering why they aren't loading/working. How you achieve this will come down to your IDE and build system, for example, Netbeans and Eclipse will allow you to add resources directly to the src directory, when you're not using maven.
At some point, you're going to want to learn about How to Use Swing Timers and How to Use Key Bindings
For some reason Graphics2D won't generate the background I am trying to set. I think the problem is something to do with renderer sending the information back to Simon the main class. I can't seem to find a solution and have been looking for hours online. If anyone know graphics 2D well or sees the issue with the code and can help that would be greatly appreciated.
package Simon;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.Timer;
public class TestingSimon implements ActionListener {
//Creating object simon
public static TestingSimon simon;
//Making integers for Width and Height for JFrame
public static final int WIDTH = 800, HEIGHT = 800;
//making a renderer for graphics2D
public Renderer renderer;
public TestingSimon() {
//Creating JFrame
JFrame frame = new JFrame("Simon Says");
//using animation for a timer
Timer timer = new Timer(20,this);
//assigning renderer to the method I create in java class Renderer
renderer = new Renderer();
//setting a size for the JFrame
frame.setSize(WIDTH + 15, HEIGHT + 35);
frame.setVisible(true);
frame.add(renderer);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
timer.start();
}
public static void main(String[] args) {
simon = new TestingSimon();
}
#Override
public void actionPerformed(ActionEvent e) {
//setting it to repaint when action event occurs
renderer.repaint();
}
public void paint(Graphics2D g) {
//trying to set background to grey using Graphics2D
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.GRAY);
}
}
//Java package Renderer
package Simon;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
/**
*
* #author chasepflueger
*/
#SuppressWarnings("serial")
//extending JPanel
public class Renderer extends JPanel
{
/**
*
* #param g
*/
//trying to implement paintComponent to Simon
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
if(TestingSimon.simon != null)
{
TestingSimon.simon.paint((Graphics2D) g);
}
}
}
//trying to set background to grey using Graphics2D
Painting the background of a component is already support by all Swing components. All you do is set the background Color:
renderer = new Renderer();
renderer.setBackground(Color.GREY); // also try Color.RED to see the difference
Painting is a function of Java components:
public void paint(Graphics2D g) {
//trying to set background to grey using Graphics2D
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.GRAY);
}
You can't just add a method to any class and expect painting to work. Your TestingSimon class is not a Component so that does nothing. Get rid of the code.
Read the section from the Swing tutorial on Custom Painting for more information and working example you can download and play with to learn the basics.
I am trying to move a JTextArea by clicking and dragging. I have the basic concept down but for some reason, when I drag it, it is showing up along the path I drag. It is easiest to explain by showing you:
I'm not sure what is wrong because I'm not creating a new JTextArea on a Mouse Drag, I am using: component.setLocation(x, y);
Why is this happening?
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.event.MouseInputAdapter;
public class Editor {
public static void main(String[] args) {
JFrame frame = new Window();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(30, 30, 1000, 700);
frame.getContentPane().setBackground(Color.white);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class Window extends JFrame {
MyPanel myPanel = new MyPanel();
private static final long serialVersionUID = 1L;
public Window() {
addMenus();
}
public void addMenus() {
getContentPane().add(myPanel);
setSize(300, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
class MyPanel extends JPanel {
private static final long serialVersionUID = 1L;
public MyPanel() {
JTextArea textArea = new JTextArea("Some text\nSome other text");
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
add(textArea);
DragListener drag = new DragListener();
textArea.addMouseListener(drag);
textArea.addMouseMotionListener(drag);
}
#Override
protected void paintComponent(Graphics g) {
}
public class DragListener extends MouseInputAdapter {
Point location;
MouseEvent pressed;
public void mousePressed(MouseEvent me) {
pressed = me;
}
public void mouseDragged(MouseEvent me) {
Component component = me.getComponent();
location = component.getLocation(location);
int x = location.x - pressed.getX() + me.getX();
int y = location.y - pressed.getY() + me.getY();
component.setLocation(x, y);
}
}
}
Painting in Swing is made up a chain of (complex) method calls. If you choose to break this chain, the you had better be ready to take over the work that this methods do...
The Graphics context is a shared resource, that is, the same Graphics context will be passed to each component involved in a given paint cycle. It is the responsibility of each component to first clear the Graphics context before performing any custom painting
You've overriden paintComponent...
#Override
protected void paintComponent(Graphics g) {
}
but you have failed to honour it's responsibilities, one of which is to clear the Graphics context before painting.
If you intend to do some custom painting, I would highly recommend calling super.paintComponent first...
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
}
or, if you have no intention of performing custom painting, remove the method altogether.
Take a look at
Painting in AWT and Swing
Performing Custom Painting
for more details
You should also have a look at Initial Threads and make sure you are intialising your UIs within the context of the Event Dispatching Thread
I'd like to make a Java panel that creates objects where the user clicks. Since my actual application uses a MVC approach I'd like also for these objects to be able to repaint themselves when a model is changed, and provide menus to change their properties.
I think that the best way to control their x and y locations would be to take a canvas based approach whereby the JPanel calls a draw method on these objects from the paintComponent method. This however will only draw the shape on the canvas and does not add the object itself loosing all abilities to control object properties. I'd be very grateful if someone could tell me the best approach for what I want to do.
I've created some sample code which can be seen below. When clicked I'd like the circle to change colour, which is implemented using a MouseListener (it basically represents changing the models properties in this small example). Also I'd just like to make sure that zooming in/out still works with any sample code/advice can provide so I've added buttons to zoom the objects in and out as a quick test.
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.geom.Ellipse2D;
public class Main {
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ExamplePanel panel = new ExamplePanel();
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
});
}
//I could not get this to with when it extended JLayeredPane
private static class ExamplePanel extends JPanel {
private static final int maxX = 500;
private static final int maxY = 500;
private static double zoom = 1;
private static final Circle circle = new Circle(100, 100);
public ExamplePanel() {
this.setPreferredSize(new Dimension(maxX, maxY));
this.setFocusable(true);
Button zoomIn = new Button("Zoom In");
zoomIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
zoom += 0.1;
repaint();
}
});
add(zoomIn);
Button zoomOut = new Button("Zoom Out");
zoomOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
zoom -= 0.1;
repaint();
}
});
add(zoomOut);
// add(circle); // Comment back in if using JLayeredPane
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.scale(zoom, zoom);
super.paintComponent(g);
circle.paint(g); // Comment out if using JLayeredPane
}
}
static class Circle extends JPanel {
private Color color = Color.RED;
private final int x;
private final int y;
private static final int DIMENSION = 100;
public Circle(int x, int y) {
// setBounds(x, y, DIMENSION, DIMENSION);
this.x = x;
this.y = y;
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
color = Color.BLUE;
}
#Override
public void mouseReleased(MouseEvent e) {
}
});
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(color);
g2.fillOval(x, y, DIMENSION, DIMENSION);
}
// I had some trouble getting this to work with JLayeredPane even when setting the bounds
// In the constructor
// #Override
// public void paintComponent(Graphics g) {
// Graphics2D g2 = (Graphics2D) g;
// g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// g2.setPaint(color);
// g2.fillOval(x, y, DIMENSION, DIMENSION);
// }
#Override
public Dimension getPreferredSize(){
return new Dimension(DIMENSION, DIMENSION);
}
}
}
As an aside I did try using a JLayeredPane(useful because I'd also like to layer my objects) but could not get my objects to even render. I know it has no default layout manager so tried calling setBounds in the circle in the constructor, but sadly it did not work. I know it's better to use a layout manager but can't seem to find one suitable for my needs!
Thanks in advance.
Don't override paint components, use paintComponent and don't forget to call super.paintComponent
A component already has a concept of "location", so when painting, the top left position of your component is actually 0x0
What you are doing is actually painting beyond the boundaries of you component
For example, if you place your Circle at 100x100 and then did...
g2.fillOval(x, y, DIMENSION, DIMENSION);
You would actually start painting at 200x200 (100 for the actual location of the component and 100 for you additional positioning).
Instead use
g2.fillOval(x, y, DIMENSION, DIMENSION);
And go back and try using JLayeredPane.
You could actually write your own layout manager that takes the location of the component and it's preferred size and updates the components bounds and then apply this to a JLayeredPane. This gives you the "benefits" of an absolute layout, but keeps you within how Swing works to update its components when things change.
You should also be careful with doing anything like...
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
The Graphics context is a shared resource. That means, anything you apply to, will still be in effect when the next component is painted. This may produce some strange results.
Instead try using...
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//...
g2.dispose();
Updated
For zooming I would take a closer look at JXLayer (or JLayer in Java 7)
The JXLayer (and excellent PBar extensions) have gone quite on the net, so you can grab a copy from here
(I tried finding a better example, but this is the best I could do with the limited time I have available)
Updated with working zooming example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.util.HashMap;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jdesktop.jxlayer.JXLayer;
import org.pbjar.jxlayer.demo.TransformUtils;
import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel;
public class TestJLayerZoom {
public static void main(String[] args) {
new TestJLayerZoom();
}
public TestJLayerZoom() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JXLayer<JComponent> layer;
private DefaultTransformModel transformModel;
private JPanel content;
public TestPane() {
content = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy = 0;
JLabel label = new JLabel("Hello");
JTextField field = new JTextField("World", 20);
content.add(label, gbc);
content.add(field, gbc);
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.REMAINDER;
final JSlider slider = new JSlider(50, 200);
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
int value = slider.getValue();
double scale = value / 100d;
transformModel.setScale(scale);
}
});
content.add(slider, gbc);
transformModel = new DefaultTransformModel();
transformModel.setScaleToPreferredSize(true);
Map<RenderingHints.Key, Object> hints = new HashMap<>();
//hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//hints.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
//hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
layer = TransformUtils.createTransformJXLayer(content, transformModel, hints);
setLayout(new BorderLayout());
add(layer);
}
}
}
I've left the rendering hints in to demonstrate their use, but I found that they screwed with the positing of the cursor within the text field, but you might like to have a play
I'd just like to add that I fixed the zooming issue not in the way suggested by the answer, but just by keeping the line that applied a scaled transform call in the ExamplePanel paintComponent method:
g2.scale(zoom, zoom);
I thought that this was the nicest implementation since none of the components require any knowledge about zooming and it seemed far simpler than JLayer since I only required basic zooming functionalities.
Trying ti change the BG image of a jpanel but i cant call poaint on any normal method, it works great when i'm building the constructor but i don't want to rebuild the constructor.
....
Sort of found a solution by putting a label in my center frame and calling setIcon but i need to be able to pull the relelevant info so i need to find a way to store a value into my Jtoggle button (the id of the Race or class so i can fetch it's picture and change the icon)
thoughts? Everything compiles outside the iff statement which is my sticking point
RaceButtons_lft[i] = new JToggleButton();
RaceButtons_lft[i].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JToggleButton cb = (JToggleButton)ae.getSource();
for (int j=0; j<MyRaceArray.size(); j++)
{
if (MyRaceArray.get(j).getraceID() == combo_contents.getIndex()){//here is my sticking point, i need to find a way to match MyRaceArray's getRaceID to some value saved withthe Toggle button
final ImageIcon BGCSMs = ScaledImageIcon("Fantasy_Landscape_01.jpg", "Profile Pic", (468-(60*2)), 285);
picLabel.setIcon(BGCSMs);
}//if
}//for
}//action performed;
});//button add action listener
Calling
super.paintComponent(..)
will probably - depending on the super class - fill the component with the background color.
public void paintComponent(Graphics g) {
// Let UI Delegate paint first, which
// includes background filling since
// this component is opaque.
super.paintComponent(g);
g.drawString("This is my custom Panel!",10,20);
redSquare.paintSquare(g);
}
(see A Closer Look at the Paint Mechanism). You don't need repaint(..) in this case.
You could be suffering from a number of problems, which we can't see because we don't have enough context...
You could have a reference issue, instead of trying to repaint the component on the screen, you've inadvertently gotten the wrong reference...
You could be shadowing your variables...
You could be painting to a opaque component...
Assuming that the code you have posted is linear (ie, it appears in you code in this exact order or close enough to it), I can see one possible problem...
ImageIcon RCicon = createImageIcon(temp_race.getActiveHeadshot(), temp_race.getRaceNameString(race.getraceID()));
Image RCimg = RCicon.getImage();
RCimg = RCimg.getScaledInstance((468-(60*2)), 285, java.awt.Image.SCALE_SMOOTH);
portraitCenterOptions.setBackground(Color.White){
protected void paintComponent(Graphics h)
{
//...//
// There is no way that this reference can be valid...
// The image created above will only have a local reference unto itself
// suggestion that you're shadowing your variables...
final ImageIcon bodypicSM = new ImageIcon(RCimg);
//...//
}
};
But without a working example, it's impossible to know...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.text.DateFormat;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ChangeBackground {
public static void main(String[] args) {
new ChangeBackground();
}
public ChangeBackground() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final PaintPane pane = new PaintPane();
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(pane);
JButton change = new JButton("Change");
change.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
pane.changeBackground();
pane.repaint();
}
});
frame.add(change, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPane extends JPanel {
private BufferedImage bg;
private int changes = 0;
public PaintPane() {
changeBackground();
}
public void changeBackground() {
bg = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bg.createGraphics();
FontMetrics fm = g.getFontMetrics();
g.setColor(getForeground());
String[] text = {
"I've been changed " + changes + " times",
"Last changed at " + DateFormat.getDateTimeInstance().format(new Date())};
int y = (200 - (fm.getHeight() * 2)) / 2;
for (String value : text) {
int x = (200 - fm.stringWidth(value)) / 2;
g.drawString(value, x, y + fm.getAscent());
y += fm.getHeight();
}
g.dispose();
changes++;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = (getWidth() - bg.getWidth()) / 2;
int y = (getHeight() - bg.getHeight()) / 2;
g.drawImage(bg, x, y, this);
}
}
}
Call repaint() on the component after you have finished your changes to the background
so ultimately tried a few thing and just got lazy, added a label in the center and called "SetIcon, does what I need it to do, thanks for the ideas though.