Diskuze: Mouse Listener
Atrament:20.9.2014 19:30
Co třeba ty obrázky zobrazovat pomocí JLabel a pak akorát sledovat MouseEventy na těch JLabelech?
Atrament:21.9.2014 17:19
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ř.
- levej horní roh (Point), pravej dolní roh (Point), danej obrázek (Image / BufferedImage,.. )
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
D0ll0k:27.9.2014 13:48
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ší.
D0ll0k:27.9.2014 20:35
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.
Atrament:28.9.2014 11:57
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);
...
Jan Vargovský:28.9.2014 21:20
Je to čtvercová (nebo také obdelníková) síť obrázků?
D0ll0k:29.9.2014 17:25
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++;
}
Atrament:29.9.2014 19:14
- Jaký je smysl toho boolean clicked?
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?
- Proc máš ve tříde Sirka, konstruktor beroucí parametr JLabel, který nastaví 'label' na to co mu předáš parametrem a zároveň v té třídě ten label vytváříš pomocí new?
- metoda add(), kterou jsem použil na posledním řádku mého příkladu slouží k vložení toho vytvořeného JLabelu do layoutu, předpokládal jsem, že budeš vytvářet ty JLabely v třídě Okno, která dědí od JFrame, nebo v Gui, která dědí od JPanel, v obou je tudíž tato funkce dostupná. Že tam do toho guláše ještě přihodíš další třídu Sirka, mně nenapadlo
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
D0ll0k:29.9.2014 19:55
Je to sedm obrázků nahoře a osm obrázků dole. Přidávám fotku.
D0ll0k:29.9.2014 20:39
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.
Jan Vargovský:29.9.2014 21:18
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
Atrament:4.10.2014 14:26
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ý.
D0ll0k:6.10.2014 21:24
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.