For some reason when i run this program instead of outputting one card choice I get 3, sometimes four.
I'm trying to pick a name from the array list include it in the path, then output the image, you can see the result with the system out.
Heres the code:
public class Main {
public static void main (String[] args) {
Main.createScreen();
}
public static void createScreen() {
JFrame p = new JFrame("Angora Realms");
p.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GameGUI g = new GameGUI();
p.add(g);
p.setLocationRelativeTo(null);
p.pack();
p.setVisible(true);
}
}
Here's where i create the GUI and also the paint:
#SuppressWarnings("serial")
public class GameGUI extends JPanel implements ActionListener {
public Button drawCard = new Button("Draw Card");
public GameGUI() {
drawCard.addActionListener(this);
add(drawCard);
}
#Override
public void actionPerformed(ActionEvent event) {
Object cause = event.getSource();
if (cause == drawCard) {
System.out.println("Ay");
repaint();
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Cards c = new Cards();
g.drawImage(c.getImage(), 0, 0, 450, 700, this);
}
}
And here is where i choose what card to load:
public class Cards {
static Random random = new Random();
public static String getCard() {
String card = null;
String[] possibleCards = new String[] {"Cheetah", "Lion"};
card = possibleCards[random.nextInt(2)];
System.out.println(card);
return card;
}
public Image getImage() {
Image img = null;
try {
img = ImageIO.read(getClass().getResource("/dev/angora/images/plains/" + Cards.getCard() + ".png"));
}
catch (IOException e) {
e.printStackTrace();
}
return img;
}
}
When I run the code I get 4 system print outs of a random variation of Cheetah and Lion. I've been told before that I'm actually creating 3 instances of my code somewhere, but I have no idea where...
You don't entirely get to decide how and when paintComponent() gets executed, and that usually doesn't matter, because all the method is supposed to do is to paint the component. It gets called when you do a repaint(), but it also gets called when Swing thinks the UI needs to get updated (which can be when the window changes focus, it gets resized or a bunch of other reasons).
However, you've given it some responsibility that it shouldn't haveāto instantiate Cards.
Move Cards c = new Cards(); from paintComponent() into actionPerformed(ActionEvent event) where it belongs and you should be fine.
how else could i input a variable into the graphics method?
In general, you have a setter method and then you save the data as an instance variable in your class that the painting method can reference.. This is how methods like setBackground(...), setForeground(...), setFont(...) work.
So maybe you have a method like drawCard(...) in your class that will get a random card and set your "image" instance variable. Then you invoke repaint() in the drawCard() method so the component can repaint itself.
The component, not the application should be responsible for painting itself when a property of the component changes.
Related
In my application, I made an array to control the flag images in my output. This worked fine but when I remove an element from my array the picture doesn't change at all.
class Flag{
Image FlagImage;
int FlagNum = 0;
public Flag(int FlagNum) {
this.FlagNum = FlagNum;
try{
FlagImage = ImageIO.read(new File("flag1.png"));
}catch(Exception e){
}
}
public void Update() {
}
public void Draw(Graphics g) {
//Draw Flag
g.drawImage(FlagImage, ((FlagNum) % 3+1) * 100-100, (int)((FlagNum) / 3) * 100+100, null);
}
}
public class Flags extends JPanel {
/**
* Creates new form Flags
*/
public Flags(){
initComponents();
FlagSet.add(new Flag(1));
final Timer timer =new Timer(10, new ActionListener(){
#Override
public void actionPerformed(final ActionEvent e){
repaint();
for (Flag f: FlagSet){
f.Update();
}
}
});
}
public static ArrayList<Flag> FlagSet = new ArrayList();
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
for (Flag f: FlagSet){
f.Draw(g);
}
}
I then try to add flags like so:
flagCounter = 4;
while(flagCounter > -1){
Flags.FlagSet.add(new Flag(flagCounter));
flagCounter--;
}
Which works fine but my image doesn't change if I put in a Flgas.FlageSet.remove(//Some flag)later on. Any ideas? Thanks in advance.
It looks like you're missing a call to repaint().
Repaint is a signal sent to the drawing component to tell it that something has changed, and that it needs to call the paint methods again. In this case, as your addition to your Flags list will change how it is drawn, you should simply call repaint() after you've finished adding your flags.
I have got a problem and I'm totally new at programming I have the object the Hero and I want to use all of his methods in my game class this is what I Programmed so far:
MainGame class:
class MainGame extends JComponent implements ActionListener, KeyListener{
Image Background;
MainGame() throws IOException {
Background = ImageIO.read(getClass().getResource("Background.png"));
}
public static void main (String[] args) throws IOException {
JFrame window = new JFrame("Adventure Times");
MainGame game = new MainGame();
window.add(game);
window.pack();
window.setLocationRelativeTo(null);
window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
window.setVisible(true);
window.addKeyListener(game);
}
public void paintComponent(Graphics g) {
g.drawImage(Background, 0, 0, null);
}
public Dimension getPreferredSize() { return new Dimension(800, 600);
}
public void actionPerformed(ActionEvent e) {
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_RIGHT);
Hero.moveRight();
}
public void keyReleased(KeyEvent e) {
}
}
Hero class:
public class Hero {
public int HeroX = 0;
public int HeroY = 0;
public int HeroSpeed = 0;
private BufferedImage Hero;
public Hero() {
try {
Hero = ImageIO.read(getClass().getResource("Hero.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void Draw(Graphics g) {
g.drawImage(Hero, HeroX, HeroY, null);
}
public void moveRight() {
HeroX += HeroSpeed;
}
public void moveLeft() {
HeroX -= HeroSpeed;
}
}
To use Hero's methods in your MainGame class, you either need an instance of Hero that can call them, or the method definitions have to include the static keyword. In this application, static doesn't work, and would in fact completely break your Hero class if applied to the methods you have now, so you need to instantiate a Hero. To do this, you need to, within MainGame have the line
Hero achilles = new Hero();
With the code you currently have, however, this will throw an exception in the Hero constructor that your try statement doesn't catch, as it won't be an IOException. The exception will be a result of trying to assign a value to a data type in
Hero = ImageIO.read(getClass().getResource("Hero.png"));
In fact, the code as it is won't even compile because of the attempted definition of Hero as a member of type BufferedImage. This is illegal, as you cannot use a class name as an identifier. This is similar to doing int = 4, which makes no sense. Rename the BufferedImage wherever it's referred to and the code should compile. For instance:
private BufferedImage sprite;
Alternatively, you could name it hero with a lowercase 'h' to avoid the name collision. This is also in line with naming conventions and general best practice for Java, as well as most languages. Class names are usually capitalized, while member names are usually lowercase. For more info on naming conventions, see here.
I'm learning Java, and now that I'm over the packages hump, things are going smoothly. I can draw similarities between most things I'm learning with things I already know at least the concept of. But what on earth is going on with the following bit of code? Is it some form of constructor, or anonymous object?
Something obj = new Something()
{
private static final int num = 3;
public void meth()
{
// w/e
}
};
You got it - this creates an anonymous inner class of Something.
See also: Nested Classes (The Java Tutorial) and Anonymous Classes.
/**
* Notice there's only one thing in this that isn't defined:
* It still needs public abstract void triggerEvent();
*/
public abstract static class TopButton extends JPanel implements MouseListener {
protected ButtonPanel parent;
private String text;
public TopButton(ButtonPanel bp, String text) { parent = bp; this.text = text; addMouseListener(this); }
public void mouseClicked(MouseEvent e) { triggerEvent(); }
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public void mousePressed(MouseEvent e) { }
public void mouseReleased(MouseEvent e) { }
public abstract void triggerEvent();
public void paintComponent(Graphics g) {
super.paintComponent(g);
Color oldColor = g.getColor();
Font oldFont = g.getFont();
Font newFont = new Font(oldFont.getName(),oldFont.getStyle(),oldFont.getSize());
g.setFont(newFont);
g.setColor(Color.black);
g.drawString(text, 20, 20);
g.setFont(oldFont);
g.setColor(oldColor);
}
}
Now, when I actually define my buttons, I do this. By providing the one line it needs, the only thing that makes it different from others. Now I could make a new file for each one, and define a new class for each one. This is much simpler.
private static void loadButtonPanelButtons() {
/* This button should tell the parent to bring up the save screen */
TopButton save = new TopButton(buttonPanel,"Save") {
public void triggerEvent() { parent.triggerSave(); }
};
save.setBorder(LineBorder.createBlackLineBorder());
buttonPanel.add(save);
/* This button should tell the parent to bring up the load screen */
TopButton load = new TopButton(buttonPanel,"Load") {
public void triggerEvent() { parent.triggerLoad(); }
};
load.setBorder(LineBorder.createBlackLineBorder());
buttonPanel.add(load);
TopButton addTile = new TopButton(buttonPanel,"Add Tile") {
public void triggerEvent() { parent.triggerAddTile(); }
};
addTile.setBorder(LineBorder.createBlackLineBorder());
buttonPanel.add(addTile);
TopButton saveTiles = new TopButton(buttonPanel,"Save Tiles") {
public void triggerEvent() { parent.triggerStyleSave(); }
};
saveTiles.setBorder(LineBorder.createBlackLineBorder());
buttonPanel.add(saveTiles);
}
Now, when I handle the buttons being pressed, remember back in the definition of TopButton... there was
public void mouseClicked(MouseEvent e) { triggerEvent(); }
We know triggerEvent() eventually gets defined. We can define it on a per-button basis, and when the panel gets clicked, no matter what we defined triggerEvent() to be, it gets called.
Such construct creates an anonymous inner class of a class where this construct is executed, and derived from Something (not an inner class of Something).
The idea is to quickly provide implementations for abstract classes, interfaces, or override some functionality of a class.
(new Thread(){ public void run() { System.out.println("executed on another thread"); }}).start();
So, what I have is a program that plots Phase trajectories. At the moment the starting points are all random, but what I am trying to add is a way for the program to start a trajectory from the point I click on. I've been fiddling with it for hours, trying everything I know, well here's the code:
public static void click(final double r, final double t) {
MouseListener mus = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
double r = e.getX();
double t = e.getY();
}
};
}
public Vector<Graph> getGraphs() {
// ... bunch of code that draws the graph...
g.add(new Graph.Line());
g.lastElement().add(r, t);
g.lastElement().setColor(Color.blue);
And what it tells me is that r and t can't be found. I realize that it might be hard to help without the whole code, but it is loads of code, I can email it to someone if you are really willing to help. But in any other case, anyone got an idea what I can do?
1) r and t are not in scope for your getGraphs() method.
2) You don't seem to have registered your mouse adapter as a MouseListener anywhere
3) It is not clear how the click() method gets called
You need to capture the mouse clicks from a window component, let's say it is a JPanel that you are using.
Then your code would look something like this:
public class MyApplication {
private JFrame myWindow = new JFrame("My Application");
private JPanel myPanelYouCanClick = new JPanel();
public MyApplication() {
myWindow.setContantPane(myPanelYouCanClick);
myPanelYouCanClick.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
double r = e.getX();
double t = e.getY();
// Code to create your new trajectory called from here, pass
// in the values of r and t if required. Remember you are
// running on the event dispatcher thread!
}
});
myWindow.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MyApplication app = new MyApplication();
}
});
}
}
I never get "paint" written to my command line window when I use Eclipse and Run->cmd to run the program. It works fine if I run System.out.print() from paintComponent in another program. Someone who can help?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GUI extends JPanel implements KeyListener, ActionListener
{
private static final long serialVersionUID = 1L;
JFrame frmMain = new JFrame("Kodning");
JTextField text = new JTextField();
JPanel pan = new JPanel();
static char bokstav;
static int x=10, y=80;
boolean convert = false;
String s;
Timer t = new Timer(10, this);
public static void main(String[] args)
{
#SuppressWarnings("unused")
GUI g = new GUI();
}
public GUI()
{
frmMain.setSize(600, 120);
frmMain.setLayout(new GridLayout(2, 1));
frmMain.addWindowListener(hornStang());
frmMain.add(text);
frmMain.add(pan);
frmMain.setFocusable(true);
frmMain.setVisible(true);
frmMain.addKeyListener(this);
text.addKeyListener(this);
pan.addKeyListener(this);
t.start();
}
private static WindowAdapter hornStang()
{
return new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
};
}
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode()== KeyEvent.VK_ENTER)
{
System.out.println("dechifrera");
repaint();
deshiffrera(text.getText());
}
}
public void keyReleased(KeyEvent arg0){}
public void keyTyped(KeyEvent arg0){}
public void deshiffrera(String s)
{
s = this.s;
repaint();
}
#override
public void paintComponent(Graphics g)
{
System.out.println("paint");
for(int i=0;i<s.length();i++)
{
bokstav = s.charAt(i);
switch (bokstav)
{
case 'a':nere(g); hoger(g); prick(g, 0); break;
//en massa case
default:break;
}
x=x+12;
}
}
#Override
public void actionPerformed(ActionEvent e)
{
repaint();
}
}
The component must be added to a visible window/frame/component for it's paintComponent to be called.
GUI is only added as a KeyListener but is neither added to the JFrame, nor any other visible component in the code above. There is no reason for calling paintComponent since the component is not being displayed at all.
There are a number of issues with your code:
Your GUI panel is not in the frame (shouldn't it be added instead of pan?)
String s is uninitialized, which causes a NullPointerException
paint should be overridden instead of paintComponents
paint should not change the state of the component, because it can be called any time.
etc...
You probably miss the output of "System.out.println("paint");" ?
GUI-Apps under Windows cant write to the console (they dont have a console, because it would suck if every GUI-App would also open a black window).
There are two java-interpreters under windows: "javaw.exe" which is a GUI-App and silently discards any System.out-writes. And "java.exe" which is a console-app and allows writing to the console. Try to start your program with "java.exe"
I use this with AWT (not 100% sure whether it's working in Swing too...)
Graphics g = _yourcomponent_.getGraphics();
if (g != null) {
_yourcomponent_.paint(g);
// below the estimated code for Swing:
_yourcomponent_.paintComponent(g);
}