09. april 2004 - 15:10Der er
53 kommentarer og 1 løsning
frame skal have et billede ind
Jeg har en klasse som extender Frame. Heri vil jeg så gerne hente et billede ind. Jeg har læst at jeg skal gøre følgende:
g = frame.getGraphics(); Image i = Toolkit.getDefaultToolkit().createImage("billede.gif"); g.drawImage(i,x,y,width,heigth, this);
Jeg synes ikke API´et gør mig klogere. Når jeg kører programmet så kommer billedet frem engang imellem. Linjen : g.drawImage(i,x,y,width,heigth, this); retunerer altså nogen gange true og andre gange false vel at mærke uden at jeg retter noget som helst!
carsten >> Jeg er lidt ny i java så jeg har lige et spørgsmål til det du har svaret. Det virker jo. Men jeg synes det virker som om at den paint metode altid vil blive udført. Samt at jeg ikke "kan bestemme så meget". Jeg vil gerne kunne hive et billede ind på en given plads på et givent tispunkt. Jeg har lige forsøgt følgende hvor intet billede fremkommer (håber du forstår hvor jeg vil hen): public class Test extends java.awt.Frame{
public Test() { super("Test"); i = java.awt.Toolkit.getDefaultToolkit().createImage("billede.gif"); setSize(500,500); setVisible(true); paint(this.getGraphics(), i); }
Du må aldrig kalde paint() direkte, kald repaint() i stedet for. Jeg troede du skulle bruge billedet som et baggrundsbillede, derfor override paint(). Med nedenstående knap, kan du indsætte/tegne et nyt image, og nemmere styre det du vil, men resizer du framen til mindste størrelse og derefter udvider igen, vil kun det store image være synligt.
import java.awt.*; import java.awt.event.*;
public class Main_5 extends java.awt.Frame{
public Main_5() { super("Test"); i = Toolkit.getDefaultToolkit().createImage("billede.gif");
setLayout(new FlowLayout()); Button button = new Button("Tegn nyt image"); button.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ nytImage(); } });
oki det virker jo straks bedre...der kan man bare se .. tak :o) Hvordan kan det være de nye billeder forsvinder ved resizing? giv et svar igen så er point
eller for den sags skyld.. hvorfor denne heller ikke virker:
import java.awt.*;
public class main{
public static void main(String[] args) {
Main_5 ny = new Main_5(); } }
public class Main_5 extends java.awt.Frame{
public Main_5() { super("Test"); i = Toolkit.getDefaultToolkit().createImage("billede.gif");
setLayout(new FlowLayout()); setSize(500,500); setVisible(true); g = this.getGraphics(); nytImage(); }
public void nytImage(){ g.drawImage(i, 300, 150, 25, 25,this); }
Image i; Graphics g; }
Synes godt om
Slettet bruger
09. april 2004 - 18:19#8
Jeg ville tro det var fordi de klasser du har posted ikke er nestede, du prøver derimod at lave 2 public klasser i een og samme fil - det må man ikke:
Nestede klasser er (ifølge hvad jeg har forstået):
public class A { ... ... class B { ... ... class C { ... ... } } }
Klassen C er nested inden i klassen B, som er nested inden i klassen A, håber det giver nogen mening. Det du vil opnå, altså ha' en klasse main (en klasse skal forresten skrives med stort begyndelsesbogstav, altså "Main") i samme fil som Main_5, opnåes ved at du enten fjerner "public" fra Main eller Main_5. :-)
Synes godt om
Slettet bruger
09. april 2004 - 18:20#9
Hovsa, og så skal du naturligvis også sørge for at filen hedder det samme som din public klasse.
doh mig som vrøvler... jeg har ingen ting nested.. jeg kan bare godt lide at have min main klasse for sig i sin helt egen fil. så jeg har to forskellige filer henholdvis .java og .class En main.java / main.class En Main_5.java / Main_5.class Det der så undrer mig er at der ingen ting sker når jeg fra main kalder metoden nytImage. Der sker heller ingen ting hvis jeg fra konstruktøren i Main_5 kalder metoden.
corholio >> For resten så vil min java ikke kompilere hvis min main klasse er med stort. Jeg ved ikke hvorfor. I alt hvad jeg har lavet har jeg altid haft en fil med: public class main{ public static void main(String[] args){ // kald til funktioner } } Hvis jeg prøver rette en af ´de to "main" til "Main" så brokker den sig. Det samme med filnavnet. Det vil den også have med småt. Jeg har altid undret mig over det men har regnet med det er fordi det er main metoden at den er strict på hvordan det skal stå
Undskyld ventetiden, skulle lige have noget at spise.
Det er en lidt indviklet proces at forklare hvad der sker under resizing, men jeg skal prøve at gøre det kort.
Der er 2 primære måder som udløser et kald til paint() 1. System udløst paint() og 2. Applikations udløst paint()
1. System udløst forekommer når A. Når en frame første gang gøres synlig på skærmen B. Når en frame resizes C. Når en frame har været helt eller delvist dækket af en anden app.
2. Applikations udløst kald af paint() Sker når du f. eks. trykker på en knap, så skal knappen visuelt vises som værende trykket ned, dette klarer AWT for dig gennem sit 'callback' system
Derfor skal du altid kalde repaint(), ALDRIG paint(). Det eneste repaint() gør, er at kalde update() som, (hvis du ikke overrider) renser komponentens baggrund og kalder paint(). Kald af repaint() sikrer at du altid har et valid Graphics object til at gentegne. Et direkte kald til paint() udløses omgående og du kan ikke være sikker på, at systemet er gearet til at foretage denne gentegning på det tidspunkt du beslutter.
Når du resizer en frame, fremprovokerer du en system udløst paint, som bevirker at paint metoden i din frame modtager et prækonfigureret Graphics object, som er gearet til at gentegne den aktuelle komponent, objectets font, color, translate og clip rectangle bliver sat. D.v.s så længe du resizer din frame til mindre størrelse bliver clip rectangle sat til (0,0, frame.width, frame.height) og alt hvad der var indenfor det nye clip rectangle bliver gentegnet. Det gør jo, at du på et tidspunkt har resizet framen til en størrelse hvor det nye billede ikke er med i clip rectangle, derfor bliver det ikke gentegnet når din frame gøres større.
Reelt kræver det nok en 5 -10 sider i A4 format at forklare det dybt seriøs, men håber det giver mening alligevel.
_carsten >> Stort emne... men det gav da lidt mening :o) Men hvordan får jeg det til at fungere uden at have main metoden i klassen? Altså som i de to eksempler jeg kom med? Jeg forstår ikke hvorfor jeg ikke kunne fx. kalde nytImage i konstruktøren for Main_5. Eller hvis jeg hev main metoden ud af Main_5. Så virker det fint bortset jeg heller ikke her i main så kan kalde nytImage. Dvs begge steder kan jeg kalde den - men der sker ingen ting. Får bare en blank skærm
hepou >> yes jeg er med. Men der er tjek på case sentisitive her :o) .. som sagt giver jeg altid min main klasse, main metode og main fil små bogstaver hele vejen igennem.
citat: "For resten så vil min java ikke kompilere hvis min main klasse er med stort. Jeg ved ikke hvorfor."
Det var bare et svar herpå ;)
Iøvrigt er det pænere kode at skrive klassenavne (og dermed også filnavne) med stort og metode navne med småt. så er det også lettere at overskue koden når man bl.a. kalder metoder på tværs af klasserne
hepou >> hehe oki.. mig som igen ikke kan formulere mig korrekt. Jeg mente bare at jeg generelt har oplevet problemer når jeg forsøger kopilere min main.java hvis ikke både klasse, metode og filnavn er med småt... Resten husker med stor for klasser og småt for metoder :D
hepou >> bare mig som ikke skulle havde nævnt det med størrelserne... for det er slet ikke et problem i denne konkrete sag! Det var blot fordi Corholio nævnte det at jeg så snakkede lidt om det. Jeg ved ikke hvorfor ... men jeg kan blot konstatere at jeg på min pc ikke kan kan have en Main.java indeholdende public class Main....public static void Main Hos mig virker det kun hvis jeg bruger main.java indeholdende public class main....public static void main Eller så "bitcher" den når jeg vil køre programmet og siger at den ikke kan finde min main metode. Men anyway.. Det var kun en side stikker og jeg er enig i at klasser ellers er med stort og metoder med småt.
Mit problem nu er de to kommentarer jeg har givet 18.02 og 18.04... De metoder jeg har angivet er i TO forskellige filer med rigtige navne og hele pivtøjet :o) Derfor undrer det mig at der ikke sker noget hvis jeg i konstruktøren i Main_5 klassen kalder metoden nytImage. Det undrer mig også at der ikke sket noget hvis jeg i main klassen i main metoden kalder nytImage. Det fungerede fint i det eksempel carsten gav mig 17.27 hvor main metoden ligger i samme klassen Main_5 og hvor der skal trykkes på en knap Min pointe er at det må da være muligt at indsætte billedet uden at skulle trykke på en knap? Det må også være muligt fra en anden klasse eller metode at kalde en metode som indsætter et billede i en nuværende frame
Synes godt om
Slettet bruger
09. april 2004 - 20:13#21
@busshou:
Og du husker at kalde nytImage()-metoden EFTER du har udført setVisible(true) i konstruktoren ?
YES... jeg har to filer... jeg har muligvis skrevet det lidt kikset i de to kommen tarer ... men jeg synes jeg har forsøgt rede bod på det?.. Jeg har to filer, en klasse i værd
hepou >> Nej - main.java - main klasse - main metode - alt med småt Sådan har jeg altid gjort med alt jeg har lavet af småting - for alt andet "bitcher" den over når jeg kører programmet. Så det kan ikke være det som er galt. Som du selv også har sagt tidligere så skal det virke blot alt enten er med småt eller stor ikke? Problemet er den der nytImage() som jeg måske ikke helt forstår
hepou >> ja det virker når man overskriver paint metoden. Men hvorfor det? Hvis jeg gør sådan her, så kommer der ikke noget "nytImage()";: ----------------------------------------------- import java.awt.*;
public class Main_5 extends java.awt.Frame{
private Image i; private Graphics g;
public Main_5() { super("Test"); i = Toolkit.getDefaultToolkit().createImage("billede.gif");
setLayout(new FlowLayout()); setSize(500,500); setVisible(true); g = this.getGraphics(); }
public void nytImage(){ g.drawImage(i, 300, 150, 25, 25,this); }
// public void paint(Graphics g){ // if(i != null) // g.drawImage(i, 350,150, 25, 25,this); // } } ---------------------------------------------- Men hvis jeg gør sådan her så kommer der et nytImage uden man kan se det fra paint() metoden: ----------------------------------------------- import java.awt.*;
public class Main_5 extends java.awt.Frame{
private Image i; private Graphics g;
public Main_5() { super("Test"); i = Toolkit.getDefaultToolkit().createImage("billede.gif");
setLayout(new FlowLayout()); setSize(500,500); setVisible(true); g = this.getGraphics(); }
public void nytImage(){ g.drawImage(i, 300, 150, 25, 25,this); }
public void paint(Graphics g){ if(i != null) g.drawImage(i,1,1,1,1,this); } } ---------------------------------------------- Og det kan jeg leve med. Men det undrer mig at det ikke virker uden man overskriver paint() metoden?
systemet kalder metoden paint() når der skal tegnes noget i et vindue. paint() får overført et Graphics-object som man ikke selv skal oprette, men får af styresystemet.
dvs. at du faktisk kan lave din kode sådan her:
------------------------------------ public class main{
men det undre mig lidt hvis du kan få det til at virke med det her:
public void nytImage(){ g.drawImage(i, 300, 150, 25, 25,this); }
public void paint(Graphics g){ if(i != null) g.drawImage(i,1,1,1,1,this); }
Det kan jeg nemlig ikke :/
Synes godt om
Slettet bruger
10. april 2004 - 12:59#45
jamen, HOVSA....
nytImage()-metoden vil vel egentligt kun vise sit billede indtil paint-metoden bliver kaldt, eller er jeg bare helt gal på den?, ville det ikke være smartere at lave en form for:
public void nytImage(Image img){ i = img }
public void paint(Graphics g){ super.paint(g); if(i != null) g.drawImage(i,1,1,1,1,this); }
Jeg har i hvert fald altid gjort det på en sådan måde, bare et forslag... se om du kan bruge det til noget :-)
Synes godt om
Slettet bruger
10. april 2004 - 13:00#46
Måske burde man også smide en Mediatracker på til at overveje indlæsningen af Images???
>Men det undrer mig at det ikke virker uden man overskriver paint() metoden? Det forstår jeg ikke, det er jo netop det som er det essentielle i AWT, du skal override paint for at det virker. nytImage() bliver kaldt og dit image bliver tegnet, men update() rydder baggrunden og paint() gentegner framen og dermed slettes dit image.
INGEN af de eksempler du vist i kommentaren 10/04-2004 09:47:38 vil virke Dog virker nedenstående, men den tegner et image som ligger på position 1,1 og størrelsen er 1 x 1 pixel. Størrelsen 1x1 kunne man måske godt være heldig at se, men positionen 1,1 gør at dit image bliver tegnet oppe bag titellinien, og det gør jo selv sagt at det ikke er synligt.
public void paint(Graphics g){ if(i != null) g.drawImage(i,1,1,1,1,this); }
M.h.t din kommentar 09/04-2004 17:18:04 Ja - paint() bliver altid udført, ligeledes gør update() når systemet opdager at der er behov for det.
M.h.t din kommentar 09/04-2004 18:04:10 Nej - det virker ikke, for uanset hvad du gør, vil AWT som det sidste rydde banen ved at kalde paint()
Gør du det derimod som jeg har vist i kom.: 09/04-2004 17:27:18 eller 09/04-2004 16:09:03 vil din frame være fuldt initieret og paint() kaldes ikke før systemet igen opdager at der er behov for det.
Hvis du absolut vil bruge en ny metode til at tegne dit image, så lad paint() kalde metoden eller put dit image i en Label og lad metoden nytImage() adde den Label til din frame på den ønskede position, det vil sikkert være nødvendigt at kalde minLabel.repaint() derefter.
hvis overstående kode bliver udført, vil man kunne tjekke at img != null MEN dette betyder ikke at hele Image-objektet er konstrueret. Sætter man så en mediatracker til at lytte på img-objektet, vil tråden som udfører koden vente indtil img er fuldstændig indlæst :-)
Synes godt om
Slettet bruger
10. april 2004 - 13:08#50
og overstående var en kommentar til 10/04-2004 13:04:25 :-)
_carsten >> sorry ventetiden men var lige ude i det gode vejr. Jeg tror det er mig som ikke helt forstår det med at den kalder paint automatisk. Men jeg er også lidt ny så håber I kan "bære over med mig". Måske jeg skal forsøge at forklare bedre hvad jeg søger. 1) Mit program åbner en frame. 2) Der bliver tegnet nogle forskellige figurer 3) Der skal tegnes forskellige billeder fra gif filer på de forskellige figurer uden at de eksisterende figurer forsvinder. 4) Ved tryk på nogle knapper kan der enten dannes nye figurer i den eksisterende frame eller fjernes figurer.
Som jeg har det nu virker alt i punkt 1,2 og 4. Og jeg kan fint oprette og fjerne figurer / tegninger. Men det går galt når jeg vil "importere" et gif billede. Jeg vil egentlig bare gerne have en funktion som jeg kan give en sti til et billede samt en position hvor billedet skal tegnes. Hvorefter funktionen -uden at fjerne noget i den aktuelle frame- opretter billedet det angivne sted i den aktuelle frame.
Fandt på at bruge ImageIcon istedet for Image. Nu kommer billedet så fint ind - uden bøvl (før kom det kun nogen gange ind og der blev nogen gange visket ud) Så jeg tror det er min løsning. Hehe bortset fra jeg ikke kan se hvor man kan sætte størrelsen på et ImageIcon men det må jeg leve med
Det ændrer ikke på det faktum, at du stadig kan gøre det som du egentlig ville fra starten af, prøv nedenstående eksempel som er holdt i ren AWT hele vejen igennem.
public class Draw extends Frame{ public Draw() { square = new Button("Tegn firkanter"); circle = new Button("Tegn cirkler"); choose = new Button("Vælg image");
addMouseListener(new MouseAdapter(){ public void mousePressed(MouseEvent evt) { x = evt.getX(); y = evt.getY(); tegn(evt); } public void mouseReleased(MouseEvent evt) { tegn(evt); } });
tak carsten... tror jeg sætter mig og leger med det sidste du gav mig :o)
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.