Diskuze: Mouse Listener
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 18 zpráv z 18.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.
Co třeba ty obrázky zobrazovat pomocí JLabel a pak akorát sledovat MouseEventy na těch JLabelech?
Tak jeden způsob by mohl třeba vypadat takto:
...
ImageIcon ii1 = new ImageIcon(this.getClass().getResource("sirka.png"));
JLabel label1 = new JLabel(ii1);
label1.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
//Tady bude kód co se spustí po kliknutí...
}
});
this.add(label1);
...
Tak pokud by jsi chtěl třídu obrázku, tak si můžeš udělat datový položky např.
Následně by sis mohl udělat např. ArrayList týhle třídy, následně by jsi musel prolejzat tenhle ArrayList a testovat jestli nakliknutej bod patří onomu obrázku nebo ne
Jednoduché ak som ťa pochopil správne síce som moc tvoj kód nečítal
ale skús to takto... Vždy keď klikneš myšou vypýtaj si jej polohu na
obrazovke, potom použi metódu intersects alebo tak nejako sa to volá majú ju
objekty typu rectangle aby vedeli či sa navzájom neprekrývajú a to je ono
kliknutím vytvoríš malý virtuálny obdĺžnik a zo súradníc obrázka
spravíš druhý a potom ich cez tú metódu porovnáš ak sa prekrývajú tak
ho zmažeš to už je na tebe... tu na to majú aj tutoriál tak si ho skús
pozrieť tu: http://www.itnetwork.cz/…sovac-kolize
Díky za radu, ale když chci, aby se změnil obrázek, musim ho nastavit na final, jenže pak ho nemůžu zase změnit nazpátek a nebo ho úplně vymazat. Taky bych tímto způsobem musel nastavit všech patnáct obrázků, což není zrovna dvakrát neúspornější.
Tak jsem už vyřešil nastavování obrázků, ale pořád tu zbývá otázka, jak přidat každýmu obrázku MouseEvent.
Tak pokud bys použil mnou navrhované řešení s pomocí JLabel, tak nastavování obrázků se děje pomocí setIcon(). Sice asi nechápu přesně co se snažíš vytvořit, ale pokud má jít o to, že máš zobrazený obrázek a po kliknutí na něj se obrázek vymění za jiný, tak je řešení s JLabel a setIcon imho nejjednodušší - prostě si vytvoříš tolik ImageIcon kolik tam chceš rotovat obrázků, jeden JLabel, kterému dodáš MouseAdapter a který zareaguje na kliknutí tím, že se podívá jaký je zrovna nastaven obrázek (getIcon() na JLabel, který si vytáhneš z eventu pomocí getSource()) a podle toho nastaví jiný obrázek (setIcon() na JLabel).
Následující příklad tak při kliknutí střídá v jednom JLabelu dva obrázky:
...
ImageIcon img1 = new ImageIcon(this.getClass().getResource("img1.png"));
ImageIcon img2 = new ImageIcon(this.getClass().getResource("img2.png"));
JLabel label1 = new JLabel(img1);
label1.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
JLabel clicked = (JLabel) e.getSource();
if (clicked.getIcon() == img1)
{
label.setIcon(img2);
}
else if (clicked.getIcon() == img2)
{
label.setIcon(img1)
}
}
});
this.add(label1);
...
Je to čtvercová (nebo také obdelníková) síť obrázků?
Ten tvůj nápad jsem použil. Akorát trochu jinak, protože jak jsi mi doporučil teď ty, hlásí mi to chybu, musim vytvořit metodu add(); Já jsem to napsal takto:
ImageIcon ii1 = new ImageIcon(this.getClass().getResource("sirka.png"));
ImageIcon ii2 = new ImageIcon(this.getClass().getResource("sirka2.png"));
JLabel label = new JLabel(ii1);
boolean clicked = true;
public Sirka(JLabel label) {
this.label = label;
label.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
Clicked();
}
});
}
public void Clicked() {
if(clicked == true) {
label.setIcon(ii2);
}else {
label.setIcon(ii1);
}
clicked = !clicked;
}
Vše mi funguje. Ve třídě Gui stačí napsat:
ImageIcon ii1 = new ImageIcon(this.getClass().getResource("sirka.png"));
JLabel label1 = new JLabel(ii1);
Sirka sirka = new Sirka(label1);
this.add(label1);
Jediné, co potřebuji je, zjistit jestli se nedá nějakým úsporným způsobem vyřešit vytváření a přidávání těch instancí s JLabelama a následné jejich vložení. Když totiž dám instance a JLabely do FOR() takto, tak to nefunguje:
int c = 0;
for(int i = 0; i < 3; i++){
String jmeno = "jlabel" + c;
JLabel jmeno + c = new JLabel(ii1);
c++;
}
2)
JLabel jmeno + c = new JLabel(ii1);
přece nemůžeš vůbec dělat, proč tam máš to '+ c'? A proč tam vůbeš děláš nějaké 'c' když už tam máš 'i', které se ti inkrementuje?
Moje rada je, dej si od toho na chvíli pauzu, projdi si znovu tutoriály
ohledně vytváření GUI ve Swingu, prostuduj si taky něco ohledně
objektového návrhu aplikací a MVC, protože to je ve Swingu velmi
důležité, tady na itnetwork je to celkem pěkně všechno vysvětlené. Pak
se k tomu vrať, zahoď všechno cos doteď napsal a začni znova
Je to sedm obrázků nahoře a osm obrázků dole. Přidávám fotku.
Boolean clicked je tam proto, aby jsem mohl vyměňovat obrázky v labelu, protože to jak jsi mi poradil ty, je nějak "zabugované". Když tam vložím dva jlabely s obrázky, kliknu na první obrázek, potom na druhý, a když chci zase na ten první, musim na něj kliknout dvakrát. Právě proto jsem si vytvořil další třídu, která mi zmenšila rozepisování. Jinak bych musel ke každému JLabelu přidat nová MouseAdapter
JLabel jmeno + c = new JLabel(ii1);
U tohoto jsem chtěl při každém cyklu vytvořit nový JLabel, který by se
jmenoval jinak. Např. jmeno1, jmeno2, jmeno3.... Já vím, že se to takhle
nedělá, jen jsem si chtěl pouze ulehčit práci.
A u metody add(). Potřebuju tam vložit patnáct obrázků s MouseAdapterem a
to, že si to dám všechno do jedné třídy mi z toho udělá guláš.
PS: Je to takové krkolomné. Musel bych ti říct do např. telefonu, jak to myslím. Takhle se mi to totiž špatně vysvětluje.
I s tím jde pracovat. Jestli jsi teda schopen získat pozici kurzoru, tak na
to běž s trochou matiky. Y souřadnici vydělíš polovinou výšky. Přímo
na příkladu, když máš výšku 100 a klikneš na Y=30, tak 30/50 = 0 =>
první řádek. Y=86, 86/50 = 1 => druhý řádek. Tak sámo uděláš i
jednotlivé sloupce. Když máš šířku dejme tomu 700 (co 100 pixelů
obrázek), tak jen vydělíš X/100 ... protože X je pozice kurzoru od myši a
když jí vydělíš 100 (700/100 - celková šířka/šířka jednoho obrázku)
tak dostaneš to samé co u toho prvního, třeba klikneš na pozici X = 96, tak
96/100 = 0 => 1. obrázek. X=524 tak 524/100 = 5 => 6. obrázek. Jen
třeba někdy uvažovat
Omluvám se, že reaguju až tak pozdě, měl jsem posledních pár dní moc práce.
Narychlo jsem si teďka zplácal prográmek, co mi zobrazí dvě řady "zápalek", a po kliknutí na kteroukoliv z ní se jí změní stav - pokud je zhasnutá tak se zapálí a naopak (prostě se prohodí dva obrázky.
Docílil jsem toho snadno pomocí JLabel, tak jak jsem navrhoval od začátku. Protože jsem ale nevěděl, že chceš 15 zápalek se stejným chováním, vedl jsem tě směrem k dělání jednoho JLabelu, který by toto obstarával. Pokud chceš těch 15 zápalek, je nejjednodušší způsob si prostě udělat třídu MyLabel, nebo Sirka, tak jak jsi to načal, ale nechat ji dědit od JLabel, a dopsat ji akorát tu svoji funkcionalitu - já jsem tam dopsal akorát metodu switchState(), která prostě přehodí ty obrázky a zavedl jsem proměnnou state, která udržuje stav té zápalky:
public class MyLabel extends JLabel {
private ImageIcon onIcon = new ImageIcon(this.getClass().getResource("sirka_on.png"));
private ImageIcon offIcon = new ImageIcon(this.getClass().getResource("sirka_off.png"));
private Boolean state;
public MyLabel() {
setIcon(onIcon);
state = true; //vytvářená zápalka je na začátku zapálená
addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
super.mouseClicked(e);
switchState();
}
});
}
public void switchState()
{
if (state)
{
state=false;
setIcon(offIcon);
}
else
{
state=true;
setIcon(onIcon);
}
}
}
Všimni si, že jsem teďka v tom MouseAdapteru overridnul mouseReleased() místo mouseClicked() - to řeší ten problém, kdy to někdy nezareagovalo na kliknutí.
S touto třídou vytvořit dvě řady patnácti sirek je otázka jednoho cyklu, například takto:
setLayout(new MigLayout());
for (int i=0;i<15;i++)
{
if (i==6)
{
add(new MyLabel(),"wrap");
}
else
{
add(new MyLabel());
}
}
pack();
Já používám jako layout MigLayout, který vřele doporučuju. Bohužel není součástí Javy takže je ho třeba stáhnout a přidat do knihoven. Ale určitě bys toho výsledku dosáhl i s nějakým klasickým Swingovským layoutem, napadá mně, že GridLayout by mohl být vhodný.
Ahoj. Ano přesně takhle jsem to udělal. Akorát jsem, jak jsi radil,
použil GridLayout, který se na toto dobře hodí. Později se chystám
přidávání jlabelu udělat pomocí pole, aby mohl i počítač odebírat
sirky, ale to je už primitivní
Zobrazeno 18 zpráv z 18.