Anropa metoder ifrån ActionPerformed (JAVA)

Tråden skapades och har fått 16 svar. Det senaste inlägget skrevs .
1

Hej! Jag läser Java i skolan och är nybörjare.

Mitt problem ligger i metoden ActionPerformed, alltså den klassen som du hamnar i om du trycker på en JButton. Om jag förstått allt rätt så räknas denna metod som en egen tråd?

Jaja, det jag vill göra är att anropa en metod i samma klass när jag trycker på en knapp.

Men det fungerar inte! Jag kan anropa metoden ifrån andra klasser och ifrån andra delar av samma klass, men inte ifrån "ActionPerformed"-metoden...

Beror det på att man byter tråd?
Hur skall jag göra för att få anropet att fatta vad det är jag menar?

class Spel extends JFrame implements ActionListener
{
	...en massa kod...

	public void trycka(int nummer)
	{
		try {Thread.sleep(300);} catch (InterruptedException e) {}
		knapp[nummer].setIcon(ner[nummer]);
		try {Thread.sleep(500);} catch (InterruptedException e) {}
		knapp[nummer].setIcon(upp[nummer]);
	}

	public void actionPerformed(ActionEvent e)
	{	
		if (e.getSource() == knapp[3])
   			trycka(3);
	}
}
  • Medlem
  • International user
  • 2004-11-30 10:37

Det borde fungera.

Har du kopplat en lyssnare till alla knappar?
Det verkar som du har lagt alla knappar i en vektor av knappar (knapp[]).

Du kopplar en lyssnare till knappen genom:

JButton knapp = new JButton("En knapp");

knapp.addActionListener(this); // skriv this, ifall denna klass implementerar gränssnittet ActionListener

Detta måste du ha, annars händer inget, när du trycker på knappen.

sedan ska du ha metoden public void actionPerformed(ActionEvent e) { }

Du har

if (e.getSource() == knapp[3])

Du ska inte använda == när du jämför två object. Använd equals() istället.

e.getSource() returnerar en objekt av typen Object.

Skriv såhär istället:

JButton src = (JButton)e.getSource();

if(src.equals(knapp[3]) )
{
// resten av koden
}

  • Medlem
  • Stockholm
  • 2004-11-30 16:25
Ursprungligen av jme:

Du ska inte använda == när du jämför två object. Använd equals() istället.

I detta fall fungerar det utmärkt att använda ==-operatorn för att kontrollera vilken knapp som är källan till eventet. Den evaluerar om de båda referenserna pekar till samma objekt vilket är precis vad vi vill i detta fall.

Alternativ förklaring i Java Language Specification:
http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html#236163

/Kalle

  • Medlem
  • International user
  • 2004-11-30 10:43

Här har du en fungerande exempel:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Test extends JFrame implements ActionListener 
{
	JButton btn;
	
	public Test()
	{
		btn = new JButton("hej");
		
		btn.addActionListener(this);
		getContentPane().add(btn);
		
		setBounds(100, 100, 300,300);
		setVisible(true);
	}
	
	public void tryck()
	{
		System.out.println("anropade metoden tryck()");
	}

	public void actionPerformed(ActionEvent e)
	{
		if(e.getSource().equals(btn) ) // det fungerar såhär också, så som du själv hade det
		{
			tryck();
		}
	}
	public static void main(String[] args) 
	{
		new Test();
	}
}

Jag har testat en hel del nu och kommit fram till att metoderna faktiskt anropas, men de gör inte som de ska!

jag tror att det är trycka() som inte fungerar. När jag först kör programet anropas visa() som anropar trycka() och då gör programet som det skall. Jag kan anropas visa() och trycka() hur många gånger jag vill ifrån både main och ifrån samma konstruktorn i klass och den fungerar alltid.

Men när jag sen försöker anropa metoden ifrån actionPerformed så fungerar den inte... varför?

//////////////////////////////////////////////////////////////////////////////////////
	public void trycka(int nummer)
	{
		try {Thread.sleep(300);} catch (InterruptedException e) {}
		knapp[nummer].setIcon(ner[nummer]);
		try {Thread.sleep(500);} catch (InterruptedException e) {}
		knapp[nummer].setIcon(upp[nummer]);

	}
//////////////////////////////////////////////////////////////////////////////////////////
	public void visa()
	{
		for(int index=0; index<knappfacit.size(); index++)
			trycka(((Integer) knappfacit.get(index)).intValue());
	}
//////////////////////////////////////////////////////////////////////////////////////////
  • Medlem
  • Stockholm
  • 2004-12-05 12:43
Ursprungligen av Gustaf Haag:

Men när jag sen försöker anropa metoden ifrån actionPerformed så fungerar den inte... varför?

Så det du försöker säga är at tdu kan anropa de aktuella metoderna manuellt men inte via actionPerformed?

I så fall, har du studerat exemplet som jme givit dig? Du måste dels loopa genom din knapp-array och skapa en ny knapp för varje element, och på samma sätt loopa genom hela arrayen och sätta rätt listener.

/Kalle

EDIT: Stavknas

Suck... jag får ingen rätsida på problemet... testat en massa saker och kommit fram till att problemet är att den hoppar över Sleep när jag anropar metoden Trycka() ifrån actionperformed...

Försökte fuska lite och la in en while-sats som räknade länge... men den struntade i den också...

Jag kan anropa metoderna från actionperformed, men när jag anropar dom därifrån så struntar den i Sleep(), det gör den inte när jag anropar dom manuellt.

  • Medlem
  • Stockholm
  • 2004-12-06 17:38
Ursprungligen av Gustaf Haag:

Jag kan anropa metoderna från actionperformed, men när jag anropar dom därifrån så struntar den i Sleep(), det gör den inte när jag anropar dom manuellt.

Det beror antagligen på att actionPerformed inte anropas från din huvud-thread utan från en tråd som hanterar events.

Edit: Mer kött på benen ==> http://www.jguru.com/faq/view.jsp?EID=8963

/Kalle

Utan att ha sett hela koden så är det ju lite svårt att säga exakt vad som händer. Men actionPerformed anropas ju från Swing's eventthread. Är du helt säker på att den verkligen anropas när du trycker ned en knapp? Får du någon InterruptedException som gör att tråden inte sover den tid du angivit?

Sen tror jag att det rent allmänt inte är någon bra ide att låta Swing's Thread anropa sleep(). Det gör väl att ditt GUI inte kan ta emot några events alls under den tiden...

public void trycka(int nummer)
	{
		try {Thread.sleep(300);} catch (InterruptedException e) {}
		knapp[nummer].setIcon(ner[nummer]);
		try {Thread.sleep(500);} catch (InterruptedException e) {}
		knapp[nummer].setIcon(upp[nummer]);
	}

Okej, jag har testat vidare och kommit fram till några saker...

När jag anropar trycka() ifrån min konstruktor är det "Thread[main,5,main]" som är igång.
Men när jag anropar trycka() ifrån actionperformed är det "Thread[AWT-EventQue-0,6,main]" som körs. Det är troligen detta som är problemet.

Jag kan sammanfatta allt så här!
Vad jag vill göra: Få en JButton att byta ImageIcon i en halv sekund.
Problemet är: När jag anropar ifrån actionperformed så sövs fel tråd.

Hjälp!

  • Medlem
  • Umeå
  • 2004-12-08 18:43

Detta borde göra det du vill utan problem (har testat )

Lånade lite kod här ovanför, men det är bara att byta ut setText() till setImageIcon() eller vad det kan vara.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonSwitchSleep extends JFrame implements ActionListener
{
	JButton btn;
	Timer timer;
	
	public ButtonSwitchSleep()
	{
		btn   = new JButton("Gammal text");
		timer = new Timer(500, this);
		
		btn.addActionListener(this);
		getContentPane().add(btn);
		setBounds(100, 100, 300,300);
		setVisible(true);
	}
	
	public void switchTo()
	{
		btn.setText("Ny Text");
		timer.start();
	}
	
	public void switchBack()
	{
		btn.setText("Gammal text");
		timer.stop();
	}
	
	public void actionPerformed(ActionEvent e)
	{
		if(e.getSource().equals(btn) )
			switchTo();
			
		if(e.getSource().equals(timer) )
			switchBack();
	}
	
	public static void main(String[] args)
	{
		new ButtonSwitchSleep();
	}
}

Funkar mycket bra! Stort tack!

for(int index=0; index<4; index++)
	mythread.start();

En fråga till... hur får jag mina "mythread"-anrop att starta efter varandra istället för samtidigt?

  • Medlem
  • Umeå
  • 2004-12-08 22:17

Jag vet inte exakt vad du gör. Försöker du starta samma tråd 4 gånger, eller ändras mythread i loopen? Om mythread ändras och det är olika trådar kanske detta fungerar (har inte testat dock)

for (int i = 0 i < 3; i++)
{
	// Fult att polla, men det funkar.
	while (oldthread != null && !oldThread.isAlive())
		;
		
	mythread.start();
	oldthread = mythread;
	
	// byt ut mythread mot en ny tråd
}

Jag hajjar inte riktigt vad din kod går ut på... dessutom så fattar inte kompilatorn .isAlive, currentThread(), join() och liknande... har jagh glömt att importera något?

  • Medlem
  • Umeå
  • 2004-12-09 22:51

Ok, vad ska denna kodsnutt göra?

for(int index=0; index<4; index++)
        mythread.start();

För mig ser det ut som om du startar en tråd 4 gånger på raken. Vad skulle det göra?

1
Bevaka tråden