I have to display images using the fly weight pattern, I can't get the images to print to screen, here's the code that demonstrates the problem.
public void draw(Graphics g, int tx, int ty, String name) {
grem.paintIcon(null, g, tx, ty);
g.drawString(name, tx, ty + H + 15 );
ImageIcon grem = new ImageIcon("../images/grem.png");
}
/// next class that calls the above class
public void paint(Graphics g) {
Folder folderIcon;
String name;
int j = 0; //count number in row
int row = Top; //start in upper left
int x = Left;
//go through all the names and folders
for (int i = 0; i< names.size(); i++) {
name = (String)names.elementAt(i);
if (name.equals(selectedName))
folderIcon = fact.getFolder(true);
else
folderIcon = fact.getFolder(false);
//have that folder draw itself at this spot
folderIcon.paint(g);
x = x + HSpace; //change to next posn
j++;
if (j >= HCount) { //reset for next row
j = 0;
row += VSpace;
x = Left;
}
}
}
Don't override paint(). Custom painting is done by overriding paintComponent().
Don't do I/O in a painting method. You can't control when Swing will repaint a component so you don't want to read images in the painting method. The images should be read in the constructor of your class.
Override the getPreferredSize(...) method to return the size of your component, otherwise the size of the component will be (0, 0) so there may be nothing to paint (depending on the layout manager being used.
If you need more help the post a proper SSCCE that demonstrates the problem because we don't know the context of how your code is being used and don't have time to spend guessing what you may or may not be doing.
Read the section from the Swing tutorial on Custom Painting for more information. Also, instead of doing custom painting you could also use a JList to display the Icon in a grid pattern. Check out the table of contents for the tutorial link to find the section on How to Use Lists for more information.
Maybe the null is the problem : it should be something like this if im not mistaken
class MyComponent extends JComponent {
public void paint(Graphics g) {
ImageIcon icon = new ImageIcon("a.png");
int x = 0;
int y = 100;
icon.paintIcon(this, g, x, y);
}
public class Gremlin extends JFrame implements ActionListener {
String names[] = {"Andy","Bill","Bob","Dan","Eugene","Frank","Gary","Harry","Ian","Jack",
"Killlian","Liam","Mark","Nial","Obi","Phil","Richard","Stephan","Terry","Viny",}; // 20 names
public Icon img = new ImageIcon("grem1.jpg");
public JLabel grem = new JLabel(img);
JLabel bigLabel = new JLabel();
JLabel grem2 = new JLabel("New Gremlin");
public JPanel panel2 = new JPanel();
JPanel panel = new JPanel();
public Gremlin() {
JButton button = new JButton("Add Gremlin");
this.add(panel);
panel.setLayout(new GridLayout(9,6));
panel.add(panel2);
panel2.add(button);
for(int i = 0; i<20; i++){
bigLabel.add(grem = new JLabel(names[i]), panel.add(grem = new JLabel(img)));
panel.add(bigLabel);
}
button.addActionListener(this);
setSize(550,600);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
Gremlin frame = new Gremlin();
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() != null ){
System.out.println("add a Gremlin");
panel.add(grem = new JLabel("NEW GREMLIN"), panel.add(grem = new JLabel(img)));
revalidate();
}
}
}
Related
Error code shown below :
The method setColor(Color) is undefined for the type JFrame
package task3;
class Execute {
public static void main(String[] args) throws Exception {
Controller c = new Controller();
c.simulate();
}
}
class Model {
int l; //line
int c; //column
int[] loc = {0,0}; //location
JFrame frame;
int m_width;
int m_height;
int R = (int)(Math.random()*256);
int G = (int)(Math.random()*256);
int B = (int)(Math.random()*256);
public int getRectWidth() {
return frame.getContentPane().getWidth() / c;
}
public int getRectHeight() {
return frame.getContentPane().getHeight() / l;
}
Model(int width, int height, int line, int column, JFrame w) {
m_width = width;
m_height = height;
l = line;
c = column;
frame = w;
}
}
class View extends JComponent {
private Model m_Mod;
View(Model mod) {
m_Mod = mod;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for(int i=0; i<m_Mod.l; ++i) {
for(int j=0; j<m_Mod.c; ++j) {
g.fillRect(m_Mod.loc[0], m_Mod.loc[1], m_Mod.getRectWidth(), m_Mod.getRectHeight());
m_Mod.loc[0] = m_Mod.loc[0] + m_Mod.getRectWidth() + 2;
}
m_Mod.loc[0] = 0;
m_Mod.loc[1] = m_Mod.loc[1] + m_Mod.getRectHeight() + 2;
}
m_Mod.loc[1] = 0;
}
}
class Controller extends JFrame{
private Model m_Mod;
private View m_View;
Controller(){
JFrame window = new JFrame();
Color color = new Color(m_Mod.R, m_Mod.G, m_Mod.B);
m_Mod.frame.setColor(color);
// Error code here : The method setColor(Color) is undefined for the type JFrame
m_Mod = new Model(500,500,3,8, window);
m_View = new View(m_Mod);
window.add(m_View);
window.setSize(m_Mod.m_width,m_Mod.m_height);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
void simulate(){
//m_View.repaint();
}
}
If I comment the Color section out the program works perfectly. Any ideas?
Furthermore the setColor() method is in the Java Frame class,no? So why is it not working?
Some sites tell me to update my library
Furthermore the setColor() method is in the Java Frame class,no?
Did you read the API? That is the first step you do when attempting to solve a problem.
You can't set the color of a JFrame. You can set the foreground/background of components added to the frame.
Typically you would use the setBackground() on the panel that you add to the frame:
m_View = new View(m_Mod);
m_View.setBackground(...); // added
window.add(m_View);
However this won't work because you are extending JComponent which doesn't paint the background by default.
If you want to extend JComponent then you need to add painting code:
super.paintComponent( g );
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor( getForeground() ); // default color for your custom painting
Or, the easier approach is to just extend JPanel since a JPanel will automatically paint the background with the color you set.
The setColor() method needs to be called inside the paintComponent method. That was my mistake here. Now it works and the rectangles are drawed in color.
What the code should do is draw X randomized shapes with the click of a button. What I have so far is a subclass that creates the random shape to be placed inside the JPanels, but the issue is that the same shape is used in all panels, I need each shape to be randomized.
The subclass looks like this:
public class Shapes extends JPanel
{
Random rand = new Random();
private int x = 5;
private int y = 5;
private int diameter = 200;
private Color outline;
private Color internal;
private Color internal2;
private Color internal3;
public Shapes() {
this(new Random());
}
//randomizes colors
public Shapes(Random rand) {
outline = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
internal = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
internal2 = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
internal3 = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
}
{
super.paintComponent(g);
g.setColor(outline);
g.drawOval(x, y, diameter, diameter);
g.setColor(internal);
g.fillOval(x+2, y+2, diameter-4, diameter-4);
g.setColor(internal2);
g.fillOval(x+25, y+66, diameter/3, diameter/3);
g.fillOval(x+125, y+66, diameter/3, diameter/3);
g.setColor(internal3);
g.fillArc(x+55, y+105, diameter/3, diameter/3, 180, 180);
}
}
While the main class looks like so [currently set up to make 6 images]:
public class ShapeGrid extends JFrame implements ActionListener
{
private JButton button;
int i = 2;
int j = 3;
JPanel[][] panelHolder = new JPanel[i][j];
private Shapes shapes;
public static void main(String[] args)
{
ShapeGrid myGrid = new ShapeGrid();
myGrid.setSize(800, 800);
myGrid.createGUI();
myGrid.setVisible(true);
}
public ShapeGrid()
{
setLayout(new GridLayout(i,j, 5, 5));
for(int m = 0; m < i; m++) {
for(int n = 0; n < j; n++) {
panelHolder[m][n] = new JPanel();
add(panelHolder[m][n]);
}
}
}
private void createGUI()
{
shape = new Shapes();
setDefaultCloseOperation(EXIT_ON_CLOSE);
button = new JButton("Press me");
add(button);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent ae)
{
if (ae.getSource() == button) {
for(int m = 0; m < i; m++) {
for(int n = 0; n < j; n++) {
shape.paintComponent(panelHolder[m][n].getGraphics());
}
}
}
}
}
shape.paintComponent(panelHolder[m][n].getGraphics());
You should NEVER invoke paintCopmonent() directly and you should never use getGraphics(). Swing will determine when a component needs to be painted and Swing will pass the Graphics object to the paintComponent() method.
Once you follow the advice below there is no need for the "Press Me" button (or the above) because the Shapes will be created when the when the ShapeGrid class is created. And the Shapes will automatically be painted when the frame is made visible.
is that the same shape is used in all panels,
You only ever create a single Shape object. You need to create a Shape object for each grid. So in the constructor of the ShapeGrid you need to create one Shape object for each grid.
I suggest you should pass in the rows/columns you want for your grid (instead of hardcoding i/j in your class). So your ShapeGrid constructor code might be something like:
public ShapeGrid(int rows, columns)
{
setLayout(new GridLayout(rows, columns, 5, 5));
int drawShapes = rows * columns;
for(int i = 0; i < drawShapes; i++) {
add( new Shape() );
}
}
That's it. There is no need for the panel holder. You will now have uniques Smileys added to the frame.
Then in your main() method you do something like:
ShapeGrid myGrid = new ShapeGrid(2, 3);
I'm trying to create an animation in which a given number of icons start on the left side of the frame and move to the right side of the screen. The icons are lined up vertically and each is supposed to run on its own thread.
How do I get all icons to do this? I tried adjusting posY when I create each racer, but so far I can only get the last racer that's created to show.
import javax.swing.*;
import java.awt.*;
public class Races {
private JFrame frame;
private JPanel gui;
private Icon img;
private int imgWidth;
private int imgHeight;
private int numOfRacers; // num of threads / racers
public static void main(String[] args) {
new Races(5);
}
public Races(int num) {
numOfRacers = num;
createGUI();
frame.add(gui);
frame.pack();
frame.setVisible(true);
}
private void createGUI() {
frame = new JFrame("Off to the Races - by Brienna Herold");
gui = new JPanel();
gui.setPreferredSize(new Dimension(imgWidth * 20, imgHeight * numOfRacers));
img = new ImageIcon("races.png");
imgWidth = img.getIconWidth();
imgHeight = img.getIconHeight();
int posY = 0;
for (int i = 0; i < numOfRacers; i++) {
System.out.println("Starting new thread..." + posY);
racer = new Racer(posY);
Thread racerThread = new Thread(racer);
racerThread.start();
posY += imgHeight;
}
}
protected class Racer extends JPanel implements Runnable {
private int lastPosX;
private int posX;
private int posY;
public Racer(int _posY) {
posX = 0;
posY = _posY;
}
#Override
public void paintComponent(Graphics g) {
// Call the method on the JPanel
super.paintComponent(g);
img.paintIcon(gui, g, posX, posY);
//posY += imgHeight;
posX += lastPosX + 3;
}
#Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
}
gui.add(racer, BorderLayout.CENTER);
You only ever add one Racer component to the frame.
but so far I can only get the last racer that's created to show.
The "racer" variable points to the last Racer component created.
If you want multiple components then you will need to create a panel using a null layout. Then you need to add each Racer component to this panel and then add the panel to the frame. Using this approach you would move the component by using the setLocation(...) method of the component.
If you want to paint an image in a different location, then you would use a single panel which would contain an ArrayList or Racer objects. Then when the paintComponent() method of the panel is invoked you iterate through the List and paint each Racer at its new location.
i am struggling to find out how to get the point in this program to change every second or two with a timer. i have tried some combinations, but that have been unsuccessful.
i believe there is something in the ActionListener that I might have failed on.
ArrayList<Point> punkter = new ArrayList<Point>();
int i = 0;
int n = 0;
public Point[] point = null;
private Timer timer;
Random rg = new Random();
public timer(){
this.setTitle("Draw");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(1010, 710);
this.setLayout(null);
this.setLocationRelativeTo(null);
point = new Point[100];
this.setVisible(true);
timer = new Timer(500,this);
timer.start();
}
public void paint(Graphics g){
super.paint(g);
for (int i = 0; i < punkter.size(); i++) {
Point a = punkter.get(i);
Point b = punkter.get((i+1)%punkter.size());
g.fillOval(a.x, a.y, 5, 5);
g.drawLine(a.x, a.y, b.x, b.y);
}
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
for(int i = 0;i < 100;i++){
point[i] = new Point(rg.nextInt(1000), rg.nextInt(700));
punkter.add(point[i]);
}
}
}
Call repaint() on the component when you wish to repaint, otherwise the paintComponent (or paint) method may not be called. Possibly not directly related but advice worth giving (and noted in a comment by trashgod): use a Component added to the JFrame (like a JPanel), and perform all the drawing within the paintComponent method of this component (if you do so, you should call repaint on this component).
i want to overlap image on button(when it is clicked)....but on clicking it is not overlapping....please guide me where i am wrong....is it not possible to do so???
i am using frame to add buttons....
import java.awt.*;
import java.awt.event.*;
public class d extends Frame implements ActionListener {
Image img, i1, i2;
int x, y;
String msg;
Button one, two;
d() {
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setSize(1000, 500);
setVisible(true);
setLayout(null);
one = new Button("1");
two = new Button("2");
add(one);
add(two);
one.addActionListener(this);
two.addActionListener(this);
one.setBounds(200, 100, 100, 100);
two.setBounds(300, 100, 100, 100);
}
public void actionPerformed(ActionEvent e) {
msg = e.getActionCommand();
if (msg.equals("1")) {
msg = "Pressed 1";
img = i1;
x = 200;
y = 100;
} else {
msg = "Pressed 2";
img = i2;
x = 300;
y = 100;
}
repaint();
}
public void paint(Graphics g) {
Toolkit tool = Toolkit.getDefaultToolkit();
i1 = tool.getImage("F:/Memories/rawk garden/a.jpg");
i2 = tool.getImage("F:/Memories/rawk garden/b.jpg");
g.drawImage(img, x, y, 100, 100, this);
g.drawString(msg, 100, 300);
}
public static void main(String s[]) {
new d();
}
}
I have already shared you code for this in your last post where I suggested you some points with the sample code to achieve it using JLabel.
Read more points...
Don't use null layout. There are lots of Layout Managers choose any one that suits as per your application design.
How to Use Various Layout Managers
From comments below:
actually I am making minesweeper type game...i want button to change into image and once one button is converted to image...that image remains there.
Use JButton#setIcon() method to set the icon of the button.
Here is the sample code where
I have created a 9x9 grid that contains buttons.
Each cell has a random boolean flag whether it has mine or not.
When button is clicked I am setting its icon if it has mine.
Simply set the text empty and make it disabled to stop further clicks on already clicked button.
sample code:
final Image mine = ImageIO.read(new File("resources/mine.png"));
final boolean[][] showMine = new boolean[9][9];
Random random = new Random();
JPanel panel = new JPanel(new GridLayout(9, 9));
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
showMine[i][j] = random.nextBoolean();
final int x = i;
final int y = j;
final JButton button = new JButton();
button.setText(String.valueOf(i * 9 + j));
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
button.setText("");
if (showMine[x][y]) {
button.setDisabledIcon(new ImageIcon(mine));
}
}
});
panel.add(button);
}
}
add(panel);
snapshot:
Setting an image on a button can be done as follows:
Button myButton = new Button(new ImageIcon("image_path"));